mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-30 15:51:53 +00:00
Compare commits
248 Commits
rr/faster_
...
1.1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
caa2d7a6ce | ||
|
|
2bd989e563 | ||
|
|
85fe2ed537 | ||
|
|
68c3ce990e | ||
|
|
d74ffc83cf | ||
|
|
661fe23479 | ||
|
|
ff2a122c42 | ||
|
|
a362275b9e | ||
|
|
b6d3a175bf | ||
|
|
f27415f5e2 | ||
|
|
2fb159f1d2 | ||
|
|
852ace7973 | ||
|
|
44ec94c5f0 | ||
|
|
99251b6d19 | ||
|
|
450345b6c1 | ||
|
|
2fa9c149fc | ||
|
|
9d2d9686a2 | ||
|
|
02bb353ed0 | ||
|
|
3db81c6252 | ||
|
|
af3c0591b7 | ||
|
|
ce79c6c7d9 | ||
|
|
5c481a0923 | ||
|
|
61cb5983bb | ||
|
|
d06af126d8 | ||
|
|
ede2acd465 | ||
|
|
f2ecdab6d1 | ||
|
|
ab618418cd | ||
|
|
ecdba7d0fd | ||
|
|
4d21631868 | ||
|
|
73673dbc72 | ||
|
|
96a84900dc | ||
|
|
e2b2d22b49 | ||
|
|
8cafb80291 | ||
|
|
6fde1efb79 | ||
|
|
4490b9b6e3 | ||
|
|
8da583458f | ||
|
|
c42fa4b309 | ||
|
|
98441430a8 | ||
|
|
d7601eccdf | ||
|
|
c7ce1b6a45 | ||
|
|
87f495a9d5 | ||
|
|
3bae7ec17f | ||
|
|
281756bd7f | ||
|
|
71eff5c469 | ||
|
|
30962096c9 | ||
|
|
416822c0c4 | ||
|
|
dae98dbc90 | ||
|
|
d9315fef92 | ||
|
|
fd2c36a6de | ||
|
|
704f1dc36f | ||
|
|
16ac28c92a | ||
|
|
91dce10322 | ||
|
|
998469f0bf | ||
|
|
3bc48d0523 | ||
|
|
dc3ee96170 | ||
|
|
c37f104e4c | ||
|
|
4ab8ffd874 | ||
|
|
7bc8458ea4 | ||
|
|
7852050139 | ||
|
|
62b290f96e | ||
|
|
b037fca737 | ||
|
|
77f9571dc9 | ||
|
|
6eddf9a36c | ||
|
|
cd6b2e0c28 | ||
|
|
7f0234f941 | ||
|
|
3c42a2db82 | ||
|
|
f44b9f0cab | ||
|
|
aab041b086 | ||
|
|
310a531f49 | ||
|
|
ec01bfe7e2 | ||
|
|
5cd9af4860 | ||
|
|
f6581740d8 | ||
|
|
e820bd1c17 | ||
|
|
16e0f0787e | ||
|
|
837eee3af1 | ||
|
|
a6ddef102c | ||
|
|
90c6536256 | ||
|
|
420b164488 | ||
|
|
84950435e8 | ||
|
|
7cdc7ce2ce | ||
|
|
8eea008a65 | ||
|
|
bfa97eef25 | ||
|
|
c60cf28674 | ||
|
|
4895625e24 | ||
|
|
d5cf6a946f | ||
|
|
f303a89aac | ||
|
|
6d951acc68 | ||
|
|
83e59c9a7e | ||
|
|
d852ca9752 | ||
|
|
900959f359 | ||
|
|
550c4f9ff9 | ||
|
|
3a5d464777 | ||
|
|
0acf6f90c8 | ||
|
|
60c5d6ddb3 | ||
|
|
f972e1a024 | ||
|
|
c9f13ef30e | ||
|
|
ea7eb50b73 | ||
|
|
c835615111 | ||
|
|
2cd139a80e | ||
|
|
732ac1afec | ||
|
|
d284e21fea | ||
|
|
68838b0279 | ||
|
|
53fe147f14 | ||
|
|
244c0de760 | ||
|
|
e59fec0f80 | ||
|
|
6ae4b885c7 | ||
|
|
6a15981b3a | ||
|
|
10c85a6add | ||
|
|
50834f9a45 | ||
|
|
06423ff0f6 | ||
|
|
3dd54719d9 | ||
|
|
8167f6f936 | ||
|
|
64462a17f6 | ||
|
|
fa2b68e928 | ||
|
|
7eaf28bc2a | ||
|
|
0c2de4865b | ||
|
|
e37729bf7a | ||
|
|
5abfba4593 | ||
|
|
d19cf32392 | ||
|
|
0e974cc49f | ||
|
|
820dfd3eaf | ||
|
|
7f7cf3fb14 | ||
|
|
5345858cbe | ||
|
|
9266ca260f | ||
|
|
8d4648951a | ||
|
|
a1ea6e026d | ||
|
|
aa79a0a7b1 | ||
|
|
e0b6180fde | ||
|
|
fd715917a5 | ||
|
|
68944aca29 | ||
|
|
9bace18109 | ||
|
|
4f0f5212b6 | ||
|
|
fb76e5dacd | ||
|
|
a497bc3e78 | ||
|
|
38fa163ee9 | ||
|
|
088fef14a1 | ||
|
|
8a615c017b | ||
|
|
e07f7ebd2f | ||
|
|
08a317ea39 | ||
|
|
839834b6a8 | ||
|
|
475ba68e57 | ||
|
|
26a0a9fee8 | ||
|
|
dc1e05c10a | ||
|
|
cb9f5653f4 | ||
|
|
e2f959ca24 | ||
|
|
55ee07b877 | ||
|
|
f10480a028 | ||
|
|
a498c7b7a7 | ||
|
|
fc56737f43 | ||
|
|
ffafe89d8c | ||
|
|
5e5c280323 | ||
|
|
ed6cfe3167 | ||
|
|
6697811244 | ||
|
|
69f99cb733 | ||
|
|
875936eefb | ||
|
|
8a97a24c9a | ||
|
|
3ae62cb3f7 | ||
|
|
342cba9ac1 | ||
|
|
b2becc8b3b | ||
|
|
52a71ec0b0 | ||
|
|
e1cdfeb533 | ||
|
|
979a5b866b | ||
|
|
a17fde20e0 | ||
|
|
60af17dc45 | ||
|
|
61a2b63046 | ||
|
|
a96adab791 | ||
|
|
7771e1ed18 | ||
|
|
825de4f4b4 | ||
|
|
e0217e2a7f | ||
|
|
6733ee9383 | ||
|
|
81276653f3 | ||
|
|
86c0c6131d | ||
|
|
9682aab423 | ||
|
|
20dfb3b91d | ||
|
|
be8764a491 | ||
|
|
f246098d05 | ||
|
|
05cd97c7ff | ||
|
|
3647252db5 | ||
|
|
25bf65e38f | ||
|
|
1d125869a0 | ||
|
|
cf40405258 | ||
|
|
802ed46be6 | ||
|
|
93bf952e8e | ||
|
|
e26ae36186 | ||
|
|
cbc717a0af | ||
|
|
16fd2a2580 | ||
|
|
1a6add09ed | ||
|
|
2b15f45de7 | ||
|
|
6528b9c6b6 | ||
|
|
39c2543b4b | ||
|
|
13c560e30a | ||
|
|
4ac2254900 | ||
|
|
c877d53d3f | ||
|
|
35b33e17d9 | ||
|
|
700f0df6e6 | ||
|
|
e889fc0495 | ||
|
|
91345c7e08 | ||
|
|
e250c01465 | ||
|
|
90760f7d29 | ||
|
|
91539caef7 | ||
|
|
7c528e324e | ||
|
|
d1e6054113 | ||
|
|
0fa75b1c59 | ||
|
|
636eb5b14f | ||
|
|
4e2690e0d3 | ||
|
|
c14f7a2063 | ||
|
|
b0906e3a1e | ||
|
|
5a68027fd4 | ||
|
|
ab52c553e1 | ||
|
|
9baf848765 | ||
|
|
3edef926ee | ||
|
|
ad9cd38566 | ||
|
|
3c33e7699d | ||
|
|
f26e20dcab | ||
|
|
c70e7ad8a7 | ||
|
|
4a3142b7d0 | ||
|
|
70370cb72c | ||
|
|
4065ffa99d | ||
|
|
782f27e765 | ||
|
|
e2726aa95e | ||
|
|
9e9f16d16e | ||
|
|
a670945b6b | ||
|
|
b6f3a0d02d | ||
|
|
ed7b517e32 | ||
|
|
cdc25dd67d | ||
|
|
5be0d53cc1 | ||
|
|
d0c9ab8b1c | ||
|
|
93acae764d | ||
|
|
a9e4513fb2 | ||
|
|
b8f423fef5 | ||
|
|
05c9b12e14 | ||
|
|
746fa581b4 | ||
|
|
8b3e8f3944 | ||
|
|
384f51d1e4 | ||
|
|
9986608a19 | ||
|
|
f352da545d | ||
|
|
a409fe7546 | ||
|
|
d9123562bb | ||
|
|
44b3092777 | ||
|
|
650220c8c8 | ||
|
|
d83bd8bf4c | ||
|
|
766eb43792 | ||
|
|
60bb823f1f | ||
|
|
efdf0744c7 | ||
|
|
345d453908 | ||
|
|
ceb0e8e072 | ||
|
|
404342d80c | ||
|
|
37bdfc4808 |
3025
ChangeLog.md
3025
ChangeLog.md
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.compilerRunner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.Argument;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.ParseCommandLineArgumentsKt;
|
||||
import org.jetbrains.kotlin.utils.StringsKt;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@@ -74,7 +75,12 @@ public class ArgumentUtils {
|
||||
|
||||
if (fieldType == boolean.class || fieldType == Boolean.class) continue;
|
||||
|
||||
result.add(value.toString());
|
||||
if (ParseCommandLineArgumentsKt.isAdvanced(argument)) {
|
||||
result.set(result.size() - 1, argument.value() + "=" + value.toString());
|
||||
}
|
||||
else {
|
||||
result.add(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> superClazz = clazz.getSuperclass();
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.build.GeneratedFile
|
||||
@@ -54,6 +53,7 @@ fun makeModuleFile(name: String, isTest: Boolean, outputDir: File, sourcesToComp
|
||||
sourcesToCompile,
|
||||
javaSourceRoots.map { JvmSourceRoot(it) },
|
||||
classpath,
|
||||
null,
|
||||
"java-production",
|
||||
isTest,
|
||||
// this excludes the output directories from the class path, to be removed for true incremental compilation
|
||||
@@ -168,10 +168,11 @@ fun<Target> OutputItemsCollectorImpl.generatedFiles(
|
||||
outputItem.sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?:
|
||||
targets.filter { getOutputDir(it)?.let { outputItem.outputFile.startsWith(it) } ?: false }.singleOrNull() ?:
|
||||
representativeTarget
|
||||
if (outputItem.outputFile.name.endsWith(".class"))
|
||||
GeneratedJvmClass(target, outputItem.sourceFiles, outputItem.outputFile)
|
||||
else
|
||||
GeneratedFile(target, outputItem.sourceFiles, outputItem.outputFile)
|
||||
|
||||
when (outputItem.outputFile.extension) {
|
||||
"class" -> GeneratedJvmClass(target, outputItem.sourceFiles, outputItem.outputFile)
|
||||
else -> GeneratedFile(target, outputItem.sourceFiles, outputItem.outputFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ class KotlinModuleXmlBuilder {
|
||||
sourceFiles: Iterable<File>,
|
||||
javaSourceRoots: Iterable<JvmSourceRoot>,
|
||||
classpathRoots: Iterable<File>,
|
||||
modularJdkRoot: File?,
|
||||
targetTypeId: String,
|
||||
isTests: Boolean,
|
||||
directoriesToFilterOut: Set<File>,
|
||||
@@ -64,6 +65,10 @@ class KotlinModuleXmlBuilder {
|
||||
processJavaSourceRoots(javaSourceRoots)
|
||||
processClasspath(classpathRoots, directoriesToFilterOut)
|
||||
|
||||
if (modularJdkRoot != null) {
|
||||
p.println("<", MODULAR_JDK_ROOT, " ", PATH, "=\"", getEscapedPath(modularJdkRoot), "\"/>")
|
||||
}
|
||||
|
||||
closeTag(p, MODULE)
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -35,8 +35,13 @@ import java.util.List;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
|
||||
|
||||
public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject> {
|
||||
@NotNull
|
||||
public final KtPureClassOrObject myClass;
|
||||
|
||||
@NotNull
|
||||
public final OwnerKind kind;
|
||||
|
||||
@NotNull
|
||||
public final ClassDescriptor descriptor;
|
||||
|
||||
protected ClassBodyCodegen(
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperclassesWithoutAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.CollectionStub
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
@@ -337,7 +337,7 @@ class CollectionStubMethodGenerator(
|
||||
val access = ACC_PUBLIC or (if (synthetic) ACC_SYNTHETIC else 0)
|
||||
val asmMethod = signature.asmMethod
|
||||
val genericSignature = if (synthetic) null else signature.genericsSignature
|
||||
val mv = v.newMethod(JvmDeclarationOrigin.NO_ORIGIN, access, asmMethod.name, asmMethod.descriptor, genericSignature, null)
|
||||
val mv = v.newMethod(CollectionStub, access, asmMethod.name, asmMethod.descriptor, genericSignature, null)
|
||||
mv.visitCode()
|
||||
AsmUtil.genThrow(
|
||||
InstructionAdapter(mv),
|
||||
@@ -351,7 +351,7 @@ private val READ_ONLY_ARE_EQUAL_TO_MUTABLE_TYPE_CHECKER = KotlinTypeCheckerImpl.
|
||||
val firstClass = x.declarationDescriptor as? ClassDescriptor ?: return@withAxioms x == y
|
||||
val secondClass = y.declarationDescriptor as? ClassDescriptor ?: return@withAxioms x == y
|
||||
|
||||
val j2k = JavaToKotlinClassMap.INSTANCE
|
||||
val j2k = JavaToKotlinClassMap
|
||||
val firstReadOnly = if (j2k.isMutable(firstClass)) j2k.convertMutableToReadOnly(firstClass) else firstClass
|
||||
val secondReadOnly = if (j2k.isMutable(secondClass)) j2k.convertMutableToReadOnly(secondClass) else secondClass
|
||||
firstReadOnly.typeConstructor == secondReadOnly.typeConstructor
|
||||
|
||||
@@ -1748,7 +1748,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
int parameterOffsetInConstructor = context.closure.getCapturedParameterOffsetInConstructor(descriptor);
|
||||
// when captured parameter is singleton
|
||||
// see compiler/testData/codegen/box/objects/objectInLocalAnonymousObject.kt (fun local() captured in A)
|
||||
if (parameterOffsetInConstructor == -1) return parentResult;
|
||||
if (parameterOffsetInConstructor == -1) return adjustVariableValue(parentResult , descriptor);
|
||||
|
||||
assert parentResult instanceof StackValue.Field || parentResult instanceof StackValue.FieldForSharedVar
|
||||
: "Part of closure should be either Field or FieldForSharedVar";
|
||||
|
||||
@@ -792,7 +792,7 @@ public class FunctionCodegen {
|
||||
if (!isThereOverriddenInKotlinClass(descriptor)) {
|
||||
Method method = typeMapper.mapAsmMethod(descriptor);
|
||||
int flags = ACC_ABSTRACT | getVisibilityAccessFlag(descriptor);
|
||||
v.newMethod(JvmDeclarationOriginKt.OtherOrigin(overridden), flags, method.getName(), method.getDescriptor(), null, null);
|
||||
v.newMethod(JvmDeclarationOriginKt.AugmentedBuiltInApi(overridden), flags, method.getName(), method.getDescriptor(), null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -938,12 +938,19 @@ public class FunctionCodegen {
|
||||
capturedArgumentsCount++;
|
||||
}
|
||||
|
||||
int maskIndex = 0;
|
||||
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
|
||||
for (int index = 0; index < valueParameters.size(); index++) {
|
||||
assert valueParameters.size() > 0 : "Expecting value parameters to generate default function " + functionDescriptor;
|
||||
int firstMaskIndex = frameMap.enterTemp(Type.INT_TYPE);
|
||||
for (int index = 1; index < valueParameters.size(); index++) {
|
||||
if (index % Integer.SIZE == 0) {
|
||||
maskIndex = frameMap.enterTemp(Type.INT_TYPE);
|
||||
frameMap.enterTemp(Type.INT_TYPE);
|
||||
}
|
||||
}
|
||||
//default handler or constructor marker
|
||||
frameMap.enterTemp(AsmTypes.OBJECT_TYPE);
|
||||
|
||||
for (int index = 0; index < valueParameters.size(); index++) {
|
||||
int maskIndex = firstMaskIndex + index / Integer.SIZE;
|
||||
ValueParameterDescriptor parameterDescriptor = valueParameters.get(index);
|
||||
Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType();
|
||||
|
||||
|
||||
@@ -41,8 +41,12 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap.PlatformMutabilityMapping;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DelegationResolver;
|
||||
@@ -70,7 +74,6 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isGenericToArray;
|
||||
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isNonGenericToArray;
|
||||
@@ -256,24 +259,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private static final Map<FqName, String> KOTLIN_MARKER_INTERFACES = new HashMap<>();
|
||||
static {
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.iterator, "kotlin/jvm/internal/markers/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.iterable, "kotlin/jvm/internal/markers/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.collection, "kotlin/jvm/internal/markers/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.list, "kotlin/jvm/internal/markers/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.listIterator, "kotlin/jvm/internal/markers/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.set, "kotlin/jvm/internal/markers/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.map, "kotlin/jvm/internal/markers/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mapEntry, "kotlin/jvm/internal/markers/KMappedMarker");
|
||||
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableIterator, "kotlin/jvm/internal/markers/KMutableIterator");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableIterable, "kotlin/jvm/internal/markers/KMutableIterable");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableCollection, "kotlin/jvm/internal/markers/KMutableCollection");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableList, "kotlin/jvm/internal/markers/KMutableList");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableListIterator, "kotlin/jvm/internal/markers/KMutableListIterator");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableSet, "kotlin/jvm/internal/markers/KMutableSet");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableMap, "kotlin/jvm/internal/markers/KMutableMap");
|
||||
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableMapEntry, "kotlin/jvm/internal/markers/KMutableMap$Entry");
|
||||
static {
|
||||
for (PlatformMutabilityMapping platformMutabilityMapping : JavaToKotlinClassMap.INSTANCE.getMutabilityMappings()) {
|
||||
KOTLIN_MARKER_INTERFACES.put(
|
||||
platformMutabilityMapping.getKotlinReadOnly().asSingleFqName(),
|
||||
"kotlin/jvm/internal/markers/KMappedMarker");
|
||||
|
||||
ClassId mutableClassId = platformMutabilityMapping.getKotlinMutable();
|
||||
KOTLIN_MARKER_INTERFACES.put(
|
||||
mutableClassId.asSingleFqName(),
|
||||
"kotlin/jvm/internal/markers/K" + mutableClassId.getRelativeClassName().asString()
|
||||
.replace("MutableEntry", "Entry") // kotlin.jvm.internal.markers.KMutableMap.Entry for some reason
|
||||
.replace(".", "$")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -307,15 +307,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
for (KotlinType supertype : descriptor.getTypeConstructor().getSupertypes()) {
|
||||
if (isJvmInterface(supertype.getConstructor().getDeclarationDescriptor())) {
|
||||
FqName kotlinInterfaceName = DescriptorUtils.getFqName(supertype.getConstructor().getDeclarationDescriptor()).toSafe();
|
||||
|
||||
sw.writeInterface();
|
||||
Type jvmInterfaceType = typeMapper.mapSupertype(supertype, sw);
|
||||
sw.writeInterfaceEnd();
|
||||
String jvmInterfaceInternalName = jvmInterfaceType.getInternalName();
|
||||
|
||||
superInterfaces.add(jvmInterfaceInternalName);
|
||||
|
||||
FqName kotlinInterfaceName = DescriptorUtils.getFqName(supertype.getConstructor().getDeclarationDescriptor()).toSafe();
|
||||
String kotlinMarkerInterfaceInternalName = KOTLIN_MARKER_INTERFACES.get(kotlinInterfaceName);
|
||||
if (kotlinMarkerInterfaceInternalName != null) {
|
||||
if (typeMapper.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) {
|
||||
sw.writeInterface();
|
||||
Type kotlinCollectionType = typeMapper.mapType(supertype, sw, TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS);
|
||||
sw.writeInterfaceEnd();
|
||||
superInterfaces.add(kotlinCollectionType.getInternalName());
|
||||
}
|
||||
|
||||
kotlinMarkerInterfaces.add(kotlinMarkerInterfaceInternalName);
|
||||
}
|
||||
}
|
||||
@@ -358,9 +367,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateFunctionsForDataClasses();
|
||||
|
||||
new CollectionStubMethodGenerator(typeMapper, descriptor).generate(functionCodegen, v);
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
|
||||
new CollectionStubMethodGenerator(typeMapper, descriptor).generate(functionCodegen, v);
|
||||
|
||||
generateToArray();
|
||||
}
|
||||
|
||||
generateToArray();
|
||||
|
||||
if (context.closure != null)
|
||||
genClosureFields(context.closure, v, typeMapper);
|
||||
@@ -1047,7 +1059,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateInitializers(@NotNull ExpressionCodegen codegen) {
|
||||
public void generateInitializers(@NotNull ExpressionCodegen codegen) {
|
||||
generateInitializers(() -> codegen);
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
|
||||
iv.load(0, classType);
|
||||
|
||||
int valueParamStart = context.getEarlierScripts().size() + 1;
|
||||
int valueParamStart = context.getEarlierScripts().isEmpty() ? 1 : 2; // this + array of earlier scripts if not empty
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = scriptDescriptor.getUnsubstitutedPrimaryConstructor().getValueParameters();
|
||||
for (ValueParameterDescriptor superclassParam: ctorDesc.getValueParameters()) {
|
||||
@@ -185,18 +185,20 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
FrameMap frameMap = new FrameMap();
|
||||
frameMap.enterTemp(OBJECT_TYPE);
|
||||
|
||||
for (ScriptDescriptor importedScript : context.getEarlierScripts()) {
|
||||
frameMap.enter(importedScript, OBJECT_TYPE);
|
||||
}
|
||||
|
||||
int offset = 1;
|
||||
if (!context.getEarlierScripts().isEmpty()) {
|
||||
int scriptsParamIndex = frameMap.enterTemp(AsmUtil.getArrayType(OBJECT_TYPE));
|
||||
|
||||
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
|
||||
Type earlierClassType = typeMapper.mapClass(earlierScript);
|
||||
iv.load(0, classType);
|
||||
iv.load(offset, earlierClassType);
|
||||
offset += earlierClassType.getSize();
|
||||
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
|
||||
int earlierScriptIndex = 0;
|
||||
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
|
||||
Type earlierClassType = typeMapper.mapClass(earlierScript);
|
||||
iv.load(0, classType);
|
||||
iv.load(scriptsParamIndex, earlierClassType);
|
||||
iv.aconst(earlierScriptIndex++);
|
||||
iv.aload(OBJECT_TYPE);
|
||||
iv.checkcast(earlierClassType);
|
||||
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, methodContext, state, this);
|
||||
|
||||
@@ -70,7 +70,7 @@ public abstract class TransformationMethodVisitor extends MethodVisitor {
|
||||
// So we just do it here
|
||||
if (methodNode.instructions.size() == 0
|
||||
// MethodNode does not create a list of variables for abstract methods, so we would get NPE in accept() instead
|
||||
&& (!(delegate instanceof MethodNode) || (methodNode.access & Opcodes.ACC_ABSTRACT) == 0)
|
||||
&& (!(delegate instanceof MethodNode) || methodNode.localVariables != null)
|
||||
) {
|
||||
List<LocalVariableNode> localVariables = methodNode.localVariables;
|
||||
// visits local variables
|
||||
|
||||
@@ -941,7 +941,12 @@ public class InlineCodegen extends CallGenerator {
|
||||
assert constantValue instanceof Integer : "Mask should be of Integer type, but " + constantValue;
|
||||
maskValues.add((Integer) constantValue);
|
||||
if (maskStartIndex == -1) {
|
||||
maskStartIndex = invocationParamBuilder.getNextParameterOffset();
|
||||
maskStartIndex = 0;
|
||||
List<ParameterInfo> infos = invocationParamBuilder.listAllParams();
|
||||
for (ParameterInfo info : infos) {
|
||||
if (info instanceof CapturedParamInfo) continue;
|
||||
maskStartIndex += info.getType().getSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -134,7 +134,7 @@ fun expandMaskConditionsAndUpdateVariableNodes(node: MethodNode, maskStartIndex:
|
||||
}
|
||||
|
||||
val indexToVarNode = node.localVariables?.filter { it.index < maskStartIndex }?.associateBy { it.index } ?: emptyMap()
|
||||
val toDelete = arrayListOf<AbstractInsnNode>()
|
||||
val toDelete = linkedSetOf<AbstractInsnNode>()
|
||||
conditions.forEach {
|
||||
val jumpInstruction = it.jumpInstruction
|
||||
InsnSequence(it.maskInstruction, (if (it.expandNotDelete) jumpInstruction.next else jumpInstruction.label)).forEach {
|
||||
@@ -147,6 +147,8 @@ fun expandMaskConditionsAndUpdateVariableNodes(node: MethodNode, maskStartIndex:
|
||||
}
|
||||
}
|
||||
|
||||
node.localVariables.removeIf { it.start in toDelete && it.end in toDelete }
|
||||
|
||||
toDelete.forEach {
|
||||
node.instructions.remove(it)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||
import java.io.File
|
||||
|
||||
@@ -215,9 +215,11 @@ class GenerationState @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
private fun shouldOnlyCollectSignatures(origin: JvmDeclarationOrigin)
|
||||
= classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && origin.originKind == CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL
|
||||
= classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && origin.originKind in doNotGenerateInLightClassMode
|
||||
}
|
||||
|
||||
private val doNotGenerateInLightClassMode = setOf(CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL, BRIDGE, COLLECTION_STUB, AUGMENTED_BUILTIN_API)
|
||||
|
||||
private class LazyJvmDiagnostics(compute: () -> Diagnostics): Diagnostics {
|
||||
private val delegate by lazy(LazyThreadSafetyMode.SYNCHRONIZED, compute)
|
||||
|
||||
|
||||
@@ -1477,8 +1477,8 @@ public class KotlinTypeMapper {
|
||||
|
||||
sw.writeParametersStart();
|
||||
|
||||
for (ScriptDescriptor importedScript : importedScripts) {
|
||||
writeParameter(sw, importedScript.getDefaultType(), /* callableDescriptor = */ null);
|
||||
if (importedScripts.size() > 0) {
|
||||
writeParameter(sw, DescriptorUtilsKt.getModule(script).getBuiltIns().getArray().getDefaultType(), null);
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
|
||||
|
||||
@@ -29,7 +29,7 @@ open class DefaultValues(val defaultValue: String, val possibleValues: List<Stri
|
||||
object StringNullDefault : DefaultValues("null")
|
||||
|
||||
object LanguageVersions : DefaultValues(
|
||||
"\"" + LanguageVersion.LATEST_STABLE.versionString + "\"",
|
||||
"null",
|
||||
LanguageVersion.values().map { "\"${it.description}\"" }
|
||||
)
|
||||
|
||||
|
||||
@@ -79,9 +79,20 @@ public class K2JSCompilerArguments extends CommonCompilerArguments {
|
||||
// Advanced options
|
||||
|
||||
@GradleOption(DefaultValues.BooleanFalseDefault.class)
|
||||
@Argument(value = "-Xtypedarrays", description = "Translate primitive arrays to JS typed arrays")
|
||||
@Argument(value = "-Xtyped-arrays", description = "Translate primitive arrays to JS typed arrays")
|
||||
public boolean typedArrays;
|
||||
|
||||
@GradleOption(DefaultValues.BooleanFalseDefault.class)
|
||||
@Argument(value = "-Xfriend-modules-disabled", description = "Disable internal declaration export")
|
||||
public boolean friendModulesDisabled;
|
||||
|
||||
@Argument(
|
||||
value = "-Xfriend-modules",
|
||||
valueDescription = "<path>",
|
||||
description = "Paths to friend modules"
|
||||
)
|
||||
public String friendModules;
|
||||
|
||||
@NotNull
|
||||
public static K2JSCompilerArguments createDefaultInstance() {
|
||||
K2JSCompilerArguments arguments = new K2JSCompilerArguments();
|
||||
|
||||
@@ -29,13 +29,14 @@ class ModuleBuilder(
|
||||
private val classpathRoots = ArrayList<String>()
|
||||
private val javaSourceRoots = ArrayList<JavaRootPath>()
|
||||
private val friendDirs = ArrayList<String>()
|
||||
override var modularJdkRoot: String? = null
|
||||
|
||||
fun addSourceFiles(pattern: String) {
|
||||
sourceFiles.add(pattern)
|
||||
fun addSourceFiles(path: String) {
|
||||
sourceFiles.add(path)
|
||||
}
|
||||
|
||||
fun addClasspathEntry(name: String) {
|
||||
classpathRoots.add(name)
|
||||
fun addClasspathEntry(path: String) {
|
||||
classpathRoots.add(path)
|
||||
}
|
||||
|
||||
fun addJavaSourceRoot(rootPath: JavaRootPath) {
|
||||
|
||||
@@ -52,6 +52,7 @@ public class ModuleXmlParser {
|
||||
public static final String JAVA_SOURCE_PACKAGE_PREFIX = "packagePrefix";
|
||||
public static final String PATH = "path";
|
||||
public static final String CLASSPATH = "classpath";
|
||||
public static final String MODULAR_JDK_ROOT = "modularJdkRoot";
|
||||
|
||||
@NotNull
|
||||
public static ModuleScriptData parseModuleScript(
|
||||
@@ -172,6 +173,10 @@ public class ModuleXmlParser {
|
||||
String packagePrefix = getNullableAttribute(attributes, JAVA_SOURCE_PACKAGE_PREFIX);
|
||||
moduleBuilder.addJavaSourceRoot(new JavaRootPath(path, packagePrefix));
|
||||
}
|
||||
else if (MODULAR_JDK_ROOT.equalsIgnoreCase(qName)) {
|
||||
String path = getAttribute(attributes, PATH, qName);
|
||||
moduleBuilder.setModularJdkRoot(path);
|
||||
}
|
||||
else {
|
||||
throw createError(qName);
|
||||
}
|
||||
|
||||
@@ -52,11 +52,19 @@ open class AggregatedReplStateHistory<T1, T2>(val history1: IReplStageHistory<T1
|
||||
ReplHistoryRecord(r1.id, r1.item to r2.item)
|
||||
}
|
||||
|
||||
override fun reset(): Iterable<ILineId> = lock.write {
|
||||
assertSameSize()
|
||||
val i1 = history1.reset().toList()
|
||||
val i2 = history2.reset().toList()
|
||||
if (i1 != i2) throw IllegalStateException("Aggregated history reset lines mismatch: $i1 != $i2")
|
||||
i1
|
||||
}
|
||||
|
||||
override fun resetTo(id: ILineId): Iterable<ILineId> = lock.write {
|
||||
assertSameSize()
|
||||
val i1 = history1.resetTo(id).toList()
|
||||
val i2 = history2.resetTo(id).toList()
|
||||
if (i1 != i2) throw IllegalStateException("Aggregated history resetted lines mismatch: $i1 != $i2")
|
||||
if (i1 != i2) throw IllegalStateException("Aggregated history reset lines mismatch: $i1 != $i2")
|
||||
i1
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,14 @@ open class BasicReplStageHistory<T>(override val lock: ReentrantReadWriteLock =
|
||||
|
||||
override fun pop(): ReplHistoryRecord<T>? = lock.write { if (isEmpty()) null else removeAt(lastIndex) }
|
||||
|
||||
override fun reset(): Iterable<ILineId> {
|
||||
lock.write {
|
||||
val removed = map { it.id }
|
||||
clear()
|
||||
return removed
|
||||
}
|
||||
}
|
||||
|
||||
override fun resetTo(id: ILineId): Iterable<ILineId> {
|
||||
lock.write {
|
||||
val idx = indexOfFirst { it.id == id }
|
||||
|
||||
@@ -46,8 +46,13 @@ class GenericReplCompilingEvaluator(val compiler: ReplCompiler,
|
||||
aggregatedState.apply {
|
||||
lock.write {
|
||||
if (state1.history.size > state2.history.size) {
|
||||
state2.history.peek()?.let {
|
||||
state1.history.resetTo(it.id)
|
||||
if (state2.history.size == 0) {
|
||||
state1.history.reset()
|
||||
}
|
||||
else {
|
||||
state2.history.peek()?.let {
|
||||
state1.history.resetTo(it.id)
|
||||
}
|
||||
}
|
||||
assert(state1.history.size == state2.history.size)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cli.common.repl
|
||||
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import java.io.File
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.write
|
||||
|
||||
@@ -73,10 +74,14 @@ open class GenericReplEvaluator(val baseClasspath: Iterable<File>,
|
||||
val useScriptArgs = currentScriptArgs?.scriptArgs
|
||||
val useScriptArgsTypes = currentScriptArgs?.scriptArgsTypes?.map { it.java }
|
||||
|
||||
val constructorParams: Array<Class<*>> = (historyActor.effectiveHistory.map { it.klass.java } +
|
||||
(useScriptArgs?.mapIndexed { i, it -> useScriptArgsTypes?.getOrNull(i) ?: it?.javaClass ?: Any::class.java } ?: emptyList())
|
||||
).toTypedArray()
|
||||
val constructorArgs: Array<Any?> = (historyActor.effectiveHistory.map { it.instance } + useScriptArgs.orEmpty()).toTypedArray()
|
||||
val hasHistory = historyActor.effectiveHistory.isNotEmpty()
|
||||
|
||||
val constructorParams: Array<Class<*>> = (if (hasHistory) arrayOf<Class<*>>(Array<Any>::class.java) else emptyArray<Class<*>>()) +
|
||||
(useScriptArgs?.mapIndexed { i, it -> useScriptArgsTypes?.getOrNull(i) ?: it?.javaClass ?: Any::class.java } ?: emptyList())
|
||||
|
||||
val constructorArgs: Array<out Any?> = if (hasHistory) arrayOf(historyActor.effectiveHistory.map { it.instance }.takeIf { it.isNotEmpty() }?.toTypedArray(),
|
||||
*(useScriptArgs.orEmpty()))
|
||||
else useScriptArgs.orEmpty()
|
||||
|
||||
// TODO: try/catch ?
|
||||
val scriptInstanceConstructor = scriptClass.getConstructor(*constructorParams)
|
||||
@@ -88,14 +93,18 @@ open class GenericReplEvaluator(val baseClasspath: Iterable<File>,
|
||||
if (invokeWrapper != null) invokeWrapper.invoke { scriptInstanceConstructor.newInstance(*constructorArgs) }
|
||||
else scriptInstanceConstructor.newInstance(*constructorArgs)
|
||||
}
|
||||
catch (e: InvocationTargetException) {
|
||||
// ignore everything in the stack trace until this constructor call
|
||||
return@eval ReplEvalResult.Error.Runtime(renderReplStackTrace(e.cause!!, startFromMethodName = "${scriptClass.name}.<init>"), e.targetException as? Exception)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
historyActor.removePlaceholder(compileResult.lineId)
|
||||
|
||||
// ignore everything in the stack trace until this constructor call
|
||||
return@eval ReplEvalResult.Error.Runtime(renderReplStackTrace(e.cause!!, startFromMethodName = "${scriptClass.name}.<init>"), e as? Exception)
|
||||
}
|
||||
finally {
|
||||
historyActor.removePlaceholder(compileResult.lineId)
|
||||
}
|
||||
|
||||
historyActor.removePlaceholder(compileResult.lineId)
|
||||
historyActor.addFinal(compileResult.lineId, EvalClassWithInstanceAndLoader(scriptClass.kotlin, scriptInstance, classLoader, invokeWrapper))
|
||||
|
||||
val resultField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME).apply { isAccessible = true }
|
||||
|
||||
@@ -52,6 +52,13 @@ class ReplHistory<T>(startingHistory: CompiledHistoryList<T> = emptyList()) : Se
|
||||
}
|
||||
}
|
||||
|
||||
/* resets back complete history and returns the lines removed */
|
||||
fun reset(): SourceHistoryList<T> {
|
||||
val removed = history.map { Pair(it.first.source, it.second) }
|
||||
history.clear()
|
||||
return removed
|
||||
}
|
||||
|
||||
/* resets back to a previous line number and returns the lines removed */
|
||||
fun resetToLine(lineNumber: Int): SourceHistoryList<T> {
|
||||
val removed = arrayListOf<SourceHistoryItem<T>>()
|
||||
|
||||
@@ -41,6 +41,8 @@ interface IReplStageHistory<T> : List<ReplHistoryRecord<T>> {
|
||||
else null
|
||||
}
|
||||
|
||||
fun reset(): Iterable<ILineId>
|
||||
|
||||
fun resetTo(id: ILineId): Iterable<ILineId>
|
||||
|
||||
val lock: ReentrantReadWriteLock
|
||||
|
||||
@@ -274,11 +274,19 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
ContainerUtil.addAll(libraries, ArraysKt.filterNot(arguments.libraries.split(File.pathSeparator), String::isEmpty));
|
||||
}
|
||||
|
||||
configuration.put(JSConfigurationKeys.LIBRARIES, libraries);
|
||||
|
||||
|
||||
if (arguments.typedArrays) {
|
||||
configuration.put(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, true);
|
||||
}
|
||||
|
||||
configuration.put(JSConfigurationKeys.LIBRARIES, libraries);
|
||||
configuration.put(JSConfigurationKeys.FRIEND_PATHS_DISABLED, arguments.friendModulesDisabled);
|
||||
|
||||
if (!arguments.friendModulesDisabled && arguments.friendModules != null) {
|
||||
List<String> friendPaths = ArraysKt.filterNot(arguments.friendModules.split(File.pathSeparator), String::isEmpty);
|
||||
configuration.put(JSConfigurationKeys.FRIEND_PATHS, friendPaths);
|
||||
}
|
||||
|
||||
String moduleKindName = arguments.moduleKind;
|
||||
ModuleKind moduleKind = moduleKindName != null ? moduleKindMap.get(moduleKindName) : ModuleKind.PLAIN;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.openapi.Disposable
|
||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
@@ -93,11 +94,16 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
}
|
||||
else if (arguments.module == null) {
|
||||
for (arg in arguments.freeArgs) {
|
||||
configuration.addKotlinSourceRoot(arg)
|
||||
val file = File(arg)
|
||||
if (file.isDirectory) {
|
||||
if (file.extension == JavaFileType.DEFAULT_EXTENSION) {
|
||||
configuration.addJavaSourceRoot(file)
|
||||
}
|
||||
else {
|
||||
configuration.addKotlinSourceRoot(arg)
|
||||
if (file.isDirectory) {
|
||||
configuration.addJavaSourceRoot(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSup
|
||||
KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope, filesForFacade))
|
||||
}
|
||||
|
||||
override fun getMultifilePartClasses(partFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
//
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import gnu.trove.THashMap
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
|
||||
import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser
|
||||
@@ -36,21 +37,23 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
|
||||
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
// TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices
|
||||
// Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage,
|
||||
// which is indirectly invoked from PsiPackage.getSubPackages
|
||||
class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager {
|
||||
private val perfCounter = PerformanceCounter.create("Find Java class")
|
||||
private var index: JvmDependenciesIndex by Delegates.notNull()
|
||||
private lateinit var index: JvmDependenciesIndex
|
||||
private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex
|
||||
private val topLevelClassesCache: MutableMap<FqName, VirtualFile?> = THashMap()
|
||||
private val allScope = GlobalSearchScope.allScope(myPsiManager.project)
|
||||
private var useFastClassFilesReading = false
|
||||
|
||||
fun initialize(packagesCache: JvmDependenciesIndex, useFastClassFilesReading: Boolean) {
|
||||
this.index = packagesCache
|
||||
fun initialize(index: JvmDependenciesIndex, singleJavaFileRootsIndex: SingleJavaFileRootsIndex, useFastClassFilesReading: Boolean) {
|
||||
this.index = index
|
||||
this.singleJavaFileRootsIndex = singleJavaFileRootsIndex
|
||||
this.useFastClassFilesReading = useFastClassFilesReading
|
||||
}
|
||||
|
||||
@@ -64,6 +67,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
index.findClass(classId) { dir, type ->
|
||||
findVirtualFileGivenPackage(dir, relativeClassName, type)
|
||||
}
|
||||
?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
|
||||
}?.takeIf { it in searchScope }
|
||||
}
|
||||
|
||||
@@ -89,7 +93,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
return@getOrPut outerClass?.findInnerClass(classId.shortClassName)
|
||||
}
|
||||
|
||||
val resolver = ClassifierResolutionContext { findClass(it, searchScope) }
|
||||
val resolver = ClassifierResolutionContext { findClass(it, allScope) }
|
||||
|
||||
BinaryJavaClass(
|
||||
virtualFile,
|
||||
@@ -153,6 +157,13 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
// traverse all
|
||||
true
|
||||
}
|
||||
|
||||
result.addIfNotNull(
|
||||
singleJavaFileRootsIndex.findJavaSourceClass(classId)
|
||||
?.takeIf { it in scope }
|
||||
?.findPsiClassInVirtualFile(relativeClassName)
|
||||
)
|
||||
|
||||
if (result.isNotEmpty()) {
|
||||
return@time result.toTypedArray()
|
||||
}
|
||||
@@ -169,10 +180,10 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
//abort on first found
|
||||
false
|
||||
}
|
||||
if (found) {
|
||||
return PsiPackageImpl(myPsiManager, packageName)
|
||||
if (!found) {
|
||||
found = singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName).isNotEmpty()
|
||||
}
|
||||
return null
|
||||
return if (found) PsiPackageImpl(myPsiManager, packageName) else null
|
||||
}
|
||||
|
||||
private fun findVirtualFileGivenPackage(
|
||||
@@ -216,6 +227,11 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
true
|
||||
})
|
||||
|
||||
for (classId in singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName)) {
|
||||
assert(!classId.isNestedClass) { "ClassId of a single .java source class should not be nested: $classId" }
|
||||
result.add(classId.shortClassName.asString())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.core.CoreApplicationEnvironment
|
||||
import com.intellij.core.CoreJavaFileManager
|
||||
import com.intellij.core.JavaCoreApplicationEnvironment
|
||||
import com.intellij.core.JavaCoreProjectEnvironment
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.lang.MetaLanguage
|
||||
import com.intellij.lang.java.JavaParserDefinition
|
||||
@@ -70,17 +71,10 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
||||
import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesDynamicCompoundIndex
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JvmUpdateableDependenciesIndexFactory
|
||||
import org.jetbrains.kotlin.cli.jvm.config.*
|
||||
import org.jetbrains.kotlin.cli.jvm.index.*
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.JavaModuleInfo
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.ModuleGraph
|
||||
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||
@@ -102,6 +96,8 @@ import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleGraph
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
||||
@@ -147,6 +143,9 @@ class KotlinCoreEnvironment private constructor(
|
||||
private val sourceFiles = mutableListOf<KtFile>()
|
||||
private val rootsIndex: JvmDependenciesDynamicCompoundIndex
|
||||
|
||||
private val javaModuleFinder: CliJavaModuleFinder
|
||||
private val javaModuleGraph: JavaModuleGraph
|
||||
|
||||
val configuration: CompilerConfiguration = configuration.copy()
|
||||
|
||||
init {
|
||||
@@ -192,6 +191,9 @@ class KotlinCoreEnvironment private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
javaModuleFinder = CliJavaModuleFinder(VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL))
|
||||
javaModuleGraph = JavaModuleGraph(javaModuleFinder)
|
||||
|
||||
val initialRoots = convertClasspathRoots(configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS))
|
||||
|
||||
if (!configuration.getBoolean(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK)) {
|
||||
@@ -208,11 +210,16 @@ class KotlinCoreEnvironment private constructor(
|
||||
// REPL and kapt2 update classpath dynamically
|
||||
val indexFactory = JvmUpdateableDependenciesIndexFactory()
|
||||
|
||||
rootsIndex = indexFactory.makeIndexFor(initialRoots)
|
||||
val (roots, singleJavaFileRoots) =
|
||||
initialRoots.partition { (file) -> file.isDirectory || file.extension != JavaFileType.DEFAULT_EXTENSION }
|
||||
rootsIndex = indexFactory.makeIndexFor(roots)
|
||||
updateClasspathFromRootsIndex(rootsIndex)
|
||||
|
||||
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl)
|
||||
.initialize(rootsIndex, configuration.getBoolean(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING))
|
||||
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
|
||||
rootsIndex,
|
||||
SingleJavaFileRootsIndex(singleJavaFileRoots),
|
||||
configuration.getBoolean(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING)
|
||||
)
|
||||
|
||||
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)
|
||||
project.registerService(MetadataFinderFactory::class.java, finderFactory)
|
||||
@@ -259,28 +266,22 @@ class KotlinCoreEnvironment private constructor(
|
||||
result.add(JavaRoot(virtualFile, rootType, prefixPackageFqName))
|
||||
}
|
||||
|
||||
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
|
||||
if (jrtFileSystem != null) {
|
||||
addModularJdkRoots(jrtFileSystem, result)
|
||||
}
|
||||
addModularRoots(result)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun addModularJdkRoots(fileSystem: VirtualFileSystem, result: MutableList<JavaRoot>) {
|
||||
val graph = ModuleGraph { moduleName ->
|
||||
fileSystem.findFileByPath("/modules/$moduleName/module-info.class")?.let((JavaModuleInfo)::read) ?: run {
|
||||
report(ERROR, "Module $moduleName cannot be found in the Java runtime image")
|
||||
JavaModuleInfo(moduleName, emptyList(), emptyList())
|
||||
}
|
||||
private fun addModularRoots(result: MutableList<JavaRoot>) {
|
||||
val jrtFileSystem = javaModuleFinder.jrtFileSystem ?: return
|
||||
|
||||
val rootModules = computeRootModules(javaModuleFinder)
|
||||
val allDependencies = javaModuleGraph.getAllDependencies(rootModules).also { modules ->
|
||||
report(LOGGING, "Loading modules: $modules")
|
||||
}
|
||||
|
||||
val allReachableModules = graph.getAllReachable(listOf("java.base", "java.se")).also { modules ->
|
||||
report(LOGGING, "Loading modules exported by java.se: $modules")
|
||||
}
|
||||
|
||||
for (moduleName in allReachableModules) {
|
||||
val root = fileSystem.findFileByPath("/modules/$moduleName")
|
||||
for (moduleName in allDependencies) {
|
||||
// TODO: support modules not only from Java runtime image, but from a separate module path
|
||||
val root = jrtFileSystem.findFileByPath("/modules/$moduleName")
|
||||
if (root == null) {
|
||||
report(ERROR, "Module $moduleName cannot be found in the module graph")
|
||||
}
|
||||
@@ -290,6 +291,40 @@ class KotlinCoreEnvironment private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
// See http://openjdk.java.net/jeps/261
|
||||
private fun computeRootModules(finder: CliJavaModuleFinder): List<String> {
|
||||
val result = arrayListOf<String>()
|
||||
|
||||
val systemModules = finder.computeAllSystemModules()
|
||||
val javaSeExists = "java.se" in systemModules
|
||||
if (javaSeExists) {
|
||||
// The java.se module is a root, if it exists.
|
||||
result.add("java.se")
|
||||
}
|
||||
|
||||
fun JavaModuleInfo.exportsAtLeastOnePackageUnqualified(): Boolean = exports.any { it.toModules.isEmpty() }
|
||||
|
||||
if (!javaSeExists) {
|
||||
// If it does not exist then every java.* module on the upgrade module path or among the system modules
|
||||
// that exports at least one package, without qualification, is a root.
|
||||
for ((name, module) in systemModules) {
|
||||
if (name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) {
|
||||
result.add(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ((name, module) in systemModules) {
|
||||
// Every non-java.* module on the upgrade module path or among the system modules that exports at least one package,
|
||||
// without qualification, is also a root.
|
||||
if (!name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) {
|
||||
result.add(name)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun updateClasspathFromRootsIndex(index: JvmDependenciesIndex) {
|
||||
index.indexedRoots.forEach {
|
||||
projectEnvironment.addSourcesToClasspath(it.file)
|
||||
@@ -316,20 +351,18 @@ class KotlinCoreEnvironment private constructor(
|
||||
fun tryUpdateClasspath(files: Iterable<File>): List<File>? = updateClasspath(files.map(::JvmClasspathRoot))
|
||||
|
||||
fun contentRootToVirtualFile(root: JvmContentRoot): VirtualFile? {
|
||||
when (root) {
|
||||
is JvmClasspathRoot -> {
|
||||
return if (root.file.isFile) findJarRoot(root) else findLocalDirectory(root)
|
||||
}
|
||||
is JavaSourceRoot -> {
|
||||
return if (root.file.isDirectory) findLocalDirectory(root) else null
|
||||
}
|
||||
return when (root) {
|
||||
is JvmClasspathRoot -> if (root.file.isFile) findJarRoot(root) else findLocalFile(root)
|
||||
is JavaSourceRoot -> findLocalFile(root)
|
||||
else -> throw IllegalStateException("Unexpected root: $root")
|
||||
}
|
||||
}
|
||||
|
||||
private fun findLocalDirectory(root: JvmContentRoot): VirtualFile? {
|
||||
fun findLocalFile(path: String) = applicationEnvironment.localFileSystem.findFileByPath(path)
|
||||
|
||||
private fun findLocalFile(root: JvmContentRoot): VirtualFile? {
|
||||
val path = root.file
|
||||
val localFile = findLocalDirectory(path.absolutePath)
|
||||
val localFile = findLocalFile(path.absolutePath)
|
||||
if (localFile == null) {
|
||||
report(STRONG_WARNING, "Classpath entry points to a non-existent location: $path")
|
||||
return null
|
||||
@@ -337,9 +370,6 @@ class KotlinCoreEnvironment private constructor(
|
||||
return localFile
|
||||
}
|
||||
|
||||
internal fun findLocalDirectory(absolutePath: String): VirtualFile? =
|
||||
applicationEnvironment.localFileSystem.findFileByPath(absolutePath)
|
||||
|
||||
private fun findJarRoot(root: JvmClasspathRoot): VirtualFile? =
|
||||
applicationEnvironment.jarFileSystem.findFileByPath("${root.file}${URLUtil.JAR_SEPARATOR}")
|
||||
|
||||
|
||||
@@ -188,6 +188,16 @@ object KotlinToJVMBytecodeCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
for (module in chunk) {
|
||||
val modularJdkRoot = module.modularJdkRoot
|
||||
if (modularJdkRoot != null) {
|
||||
// We use the SDK of the first module in the chunk, which is not always correct because some other module in the chunk
|
||||
// might depend on a different SDK
|
||||
configuration.put(JVMConfigurationKeys.JDK_HOME, File(modularJdkRoot))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
configuration.addAll(JVMConfigurationKeys.MODULES, chunk)
|
||||
}
|
||||
|
||||
@@ -346,7 +356,7 @@ object KotlinToJVMBytecodeCompiler {
|
||||
override fun analyze(): AnalysisResult {
|
||||
val project = environment.project
|
||||
val moduleOutputs = environment.configuration.get(JVMConfigurationKeys.MODULES)?.mapNotNull { module ->
|
||||
environment.findLocalDirectory(module.getOutputDirectory())
|
||||
environment.findLocalFile(module.getOutputDirectory())
|
||||
}.orEmpty()
|
||||
val sourcesOnly = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, environment.getSourceFiles())
|
||||
// To support partial and incremental compilation, we add the scope which contains binaries from output directories
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.index
|
||||
|
||||
import com.intellij.lang.java.lexer.JavaLexer
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.psi.impl.source.tree.ElementType
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class SingleJavaFileRootsIndex(private val roots: List<JavaRoot>) {
|
||||
init {
|
||||
for ((file) in roots) {
|
||||
assert(!file.isDirectory) { "Should not be a directory: $file" }
|
||||
}
|
||||
}
|
||||
|
||||
private val classIdsInRoots = ArrayList<List<ClassId>>(roots.size)
|
||||
|
||||
fun findJavaSourceClass(classId: ClassId): VirtualFile? =
|
||||
roots.indices
|
||||
.find { index -> classId in getClassIdsForRootAt(index) }
|
||||
?.let { index -> roots[index].file }
|
||||
|
||||
fun findJavaSourceClasses(packageFqName: FqName): List<ClassId> =
|
||||
roots.indices.flatMap(this::getClassIdsForRootAt).filter { root -> root.packageFqName == packageFqName }
|
||||
|
||||
private fun getClassIdsForRootAt(index: Int): List<ClassId> {
|
||||
for (i in classIdsInRoots.size..index) {
|
||||
classIdsInRoots.add(JavaSourceClassIdReader(roots[i].file).readClassIds())
|
||||
}
|
||||
return classIdsInRoots[index]
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a .java file, [readClassIds] uses lexer to determine which classes are declared in that file
|
||||
*/
|
||||
private class JavaSourceClassIdReader(file: VirtualFile) {
|
||||
private val lexer = JavaLexer(LanguageLevel.JDK_1_9).apply {
|
||||
start(String(file.contentsToByteArray()))
|
||||
}
|
||||
private var braceBalance = 0
|
||||
|
||||
private fun at(type: IElementType): Boolean = lexer.tokenType == type
|
||||
|
||||
private fun end(): Boolean = lexer.tokenType == null
|
||||
|
||||
private fun advance() {
|
||||
when {
|
||||
at(ElementType.LBRACE) -> braceBalance++
|
||||
at(ElementType.RBRACE) -> braceBalance--
|
||||
}
|
||||
lexer.advance()
|
||||
}
|
||||
|
||||
private fun tokenText(): String = lexer.tokenText
|
||||
|
||||
private fun atClass(): Boolean =
|
||||
braceBalance == 0 && lexer.tokenType in CLASS_KEYWORDS
|
||||
|
||||
fun readClassIds(): List<ClassId> {
|
||||
var packageFqName = FqName.ROOT
|
||||
while (!end() && !at(ElementType.PACKAGE_KEYWORD) && !atClass()) {
|
||||
advance()
|
||||
}
|
||||
if (at(ElementType.PACKAGE_KEYWORD)) {
|
||||
val packageName = StringBuilder()
|
||||
while (!end() && !at(ElementType.SEMICOLON)) {
|
||||
if (at(ElementType.IDENTIFIER) || at(ElementType.DOT)) {
|
||||
packageName.append(tokenText())
|
||||
}
|
||||
advance()
|
||||
}
|
||||
packageFqName = FqName(packageName.toString())
|
||||
}
|
||||
|
||||
val result = ArrayList<ClassId>(1)
|
||||
|
||||
while (true) {
|
||||
while (!end() && !atClass()) {
|
||||
advance()
|
||||
}
|
||||
if (end()) break
|
||||
while (!end() && !at(ElementType.IDENTIFIER)) {
|
||||
advance()
|
||||
}
|
||||
if (end()) break
|
||||
result.add(ClassId(packageFqName, Name.identifier(tokenText())))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val CLASS_KEYWORDS = setOf(ElementType.CLASS_KEYWORD, ElementType.INTERFACE_KEYWORD, ElementType.ENUM_KEYWORD)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.modules
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFileSystem
|
||||
import com.intellij.psi.PsiJavaModule
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleFinder
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
|
||||
|
||||
internal class CliJavaModuleFinder(val jrtFileSystem: VirtualFileSystem?) : JavaModuleFinder {
|
||||
internal fun computeAllSystemModules(): Map<String, JavaModuleInfo> {
|
||||
return jrtFileSystem?.findFileByPath("/modules")?.children.orEmpty()
|
||||
.mapNotNull { root -> root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) }
|
||||
.mapNotNull((JavaModuleInfo)::read)
|
||||
.associateBy { moduleInfo -> moduleInfo.moduleName }
|
||||
}
|
||||
|
||||
override fun findModule(name: String): JavaModuleInfo? {
|
||||
val file = jrtFileSystem?.findFileByPath("/modules/$name/${PsiJavaModule.MODULE_INFO_CLS_FILE}")
|
||||
if (file != null) {
|
||||
val moduleInfo = JavaModuleInfo.read(file)
|
||||
if (moduleInfo != null) {
|
||||
return moduleInfo
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -26,16 +26,28 @@ import kotlin.script.dependencies.KotlinScriptExternalDependencies
|
||||
|
||||
class ReplCompilerStageHistory(private val state: GenericReplCompilerState) : BasicReplStageHistory<ScriptDescriptor>(state.lock) {
|
||||
|
||||
override fun reset(): Iterable<ILineId> {
|
||||
val removedCompiledLines = super.reset()
|
||||
val removedAnalyzedLines = state.analyzerEngine.reset()
|
||||
|
||||
checkConsistent(removedCompiledLines, removedAnalyzedLines)
|
||||
return removedCompiledLines
|
||||
}
|
||||
|
||||
override fun resetTo(id: ILineId): Iterable<ILineId> {
|
||||
val removedCompiledLines = super.resetTo(id)
|
||||
val removedAnalyzedLines = state.analyzerEngine.resetToLine(id.no)
|
||||
val removedAnalyzedLines = state.analyzerEngine.resetToLine(id)
|
||||
|
||||
checkConsistent(removedCompiledLines, removedAnalyzedLines)
|
||||
return removedCompiledLines
|
||||
}
|
||||
|
||||
private fun checkConsistent(removedCompiledLines: Iterable<ILineId>, removedAnalyzedLines: List<ReplCodeLine>) {
|
||||
removedCompiledLines.zip(removedAnalyzedLines).forEach {
|
||||
if (it.first != LineId(it.second)) {
|
||||
throw IllegalStateException("History mismatch when resetting lines: ${it.first.no} != ${it.second}")
|
||||
}
|
||||
}
|
||||
return removedCompiledLines
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package org.jetbrains.kotlin.cli.jvm.repl
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.repl.CompiledReplCodeLine
|
||||
import org.jetbrains.kotlin.cli.common.repl.ILineId
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplHistory
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
|
||||
@@ -88,7 +89,9 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
|
||||
}
|
||||
}
|
||||
|
||||
fun resetToLine(lineNumber: Int): List<ReplCodeLine> = replState.resetToLine(lineNumber)
|
||||
fun resetToLine(lineId: ILineId): List<ReplCodeLine> = replState.resetToLine(lineId)
|
||||
|
||||
fun reset(): List<ReplCodeLine> = replState.reset()
|
||||
|
||||
fun analyzeReplLine(psiFile: KtFile, codeLine: ReplCodeLine): ReplLineAnalysisResult {
|
||||
topDownAnalysisContext.scripts.clear()
|
||||
@@ -172,12 +175,17 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
|
||||
private val successfulLines = ReplHistory<LineInfo.SuccessfulLine>()
|
||||
private val submittedLines = hashMapOf<KtFile, LineInfo>()
|
||||
|
||||
fun resetToLine(lineNumber: Int): List<ReplCodeLine> {
|
||||
val removed = successfulLines.resetToLine(lineNumber)
|
||||
fun resetToLine(lineId: ILineId): List<ReplCodeLine> {
|
||||
val removed = successfulLines.resetToLine(lineId.no)
|
||||
removed.forEach { submittedLines.remove(it.second.linePsi) }
|
||||
return removed.map { it.first }
|
||||
}
|
||||
|
||||
fun reset(): List<ReplCodeLine> {
|
||||
submittedLines.clear()
|
||||
return successfulLines.reset().map { it.first }
|
||||
}
|
||||
|
||||
fun submitLine(ktFile: KtFile, codeLine: ReplCodeLine) {
|
||||
val line = LineInfo.SubmittedLine(ktFile, successfulLines.lastValue())
|
||||
submittedLines[ktFile] = line
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.cli.jvm.repl
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.LineResult.*
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
@@ -86,7 +86,7 @@ class ReplFromTerminal(
|
||||
}
|
||||
|
||||
val lineResult = eval(line)
|
||||
if (lineResult is LineResult.Incomplete) {
|
||||
if (lineResult is ReplEvalResult.Incomplete) {
|
||||
return WhatNextAfterOneLine.INCOMPLETE
|
||||
}
|
||||
else {
|
||||
@@ -94,20 +94,20 @@ class ReplFromTerminal(
|
||||
}
|
||||
}
|
||||
|
||||
private fun eval(line: String): LineResult {
|
||||
val lineResult = replInterpreter.eval(line)
|
||||
when (lineResult) {
|
||||
is ValueResult, UnitResult -> {
|
||||
private fun eval(line: String): ReplEvalResult {
|
||||
val evalResult = replInterpreter.eval(line)
|
||||
when (evalResult) {
|
||||
is ReplEvalResult.ValueResult, is ReplEvalResult.UnitResult -> {
|
||||
writer.notifyCommandSuccess()
|
||||
if (lineResult is ValueResult) {
|
||||
writer.outputCommandResult(lineResult.valueAsString)
|
||||
if (evalResult is ReplEvalResult.ValueResult) {
|
||||
writer.outputCommandResult(evalResult.value.toString())
|
||||
}
|
||||
}
|
||||
Incomplete -> writer.notifyIncomplete()
|
||||
is Error.CompileTime -> writer.outputCompileError(lineResult.errorText)
|
||||
is Error.Runtime -> writer.outputRuntimeError(lineResult.errorText)
|
||||
is ReplEvalResult.Error.Runtime -> writer.outputRuntimeError(evalResult.message)
|
||||
is ReplEvalResult.Error.CompileTime -> writer.outputRuntimeError(evalResult.message)
|
||||
is ReplEvalResult.Incomplete -> writer.notifyIncomplete()
|
||||
}
|
||||
return lineResult
|
||||
return evalResult
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
|
||||
@@ -16,143 +16,80 @@
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.repl
|
||||
|
||||
import com.google.common.base.Throwables
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.vfs.CharsetToolkit
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.impl.PsiFileFactoryImpl
|
||||
import com.intellij.testFramework.LightVirtualFile
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplClassLoader
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||
import org.jetbrains.kotlin.cli.common.repl.*
|
||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
|
||||
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
|
||||
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import java.io.PrintWriter
|
||||
import java.net.URLClassLoader
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class ReplInterpreter(
|
||||
disposable: Disposable,
|
||||
private val configuration: CompilerConfiguration,
|
||||
private val replConfiguration: ReplConfiguration
|
||||
): ReplConfiguration by replConfiguration {
|
||||
private var lineNumber = 0
|
||||
|
||||
private val earlierLines = arrayListOf<EarlierLine>()
|
||||
private val lineNumber = AtomicInteger()
|
||||
|
||||
private val previousIncompleteLines = arrayListOf<String>()
|
||||
private val classLoader: ReplClassLoader = run {
|
||||
val classpath = configuration.jvmClasspathRoots.map { it.toURI().toURL() }
|
||||
ReplClassLoader(URLClassLoader(classpath.toTypedArray(), null))
|
||||
}
|
||||
|
||||
private val environment = run {
|
||||
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, REPL_LINE_AS_SCRIPT_DEFINITION)
|
||||
KotlinCoreEnvironment.createForProduction(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
private val messageCollector = object : MessageCollector {
|
||||
private var hasErrors = false
|
||||
private val messageRenderer = MessageRenderer.WITHOUT_PATHS
|
||||
|
||||
override fun clear() {
|
||||
hasErrors = false
|
||||
}
|
||||
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
val msg = messageRenderer.render(severity, message, location)
|
||||
with (replConfiguration.writer) {
|
||||
when (severity) {
|
||||
CompilerMessageSeverity.EXCEPTION -> sendInternalErrorReport(msg)
|
||||
CompilerMessageSeverity.ERROR -> outputCompileError(msg)
|
||||
CompilerMessageSeverity.STRONG_WARNING -> {} // TODO consider reporting this and two below
|
||||
CompilerMessageSeverity.WARNING -> {}
|
||||
CompilerMessageSeverity.INFO -> {}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasErrors(): Boolean = hasErrors
|
||||
}
|
||||
|
||||
private val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
|
||||
private val analyzerEngine = ReplCodeAnalyzer(environment)
|
||||
// TODO: add script definition with project-based resolving for IDEA repl
|
||||
private val scriptCompiler: ReplCompiler by lazy { GenericReplCompiler(disposable, REPL_LINE_AS_SCRIPT_DEFINITION, configuration, messageCollector) }
|
||||
private val scriptEvaluator: ReplFullEvaluator by lazy { GenericReplCompilingEvaluator(scriptCompiler, configuration.jvmClasspathRoots, classLoader, null, ReplRepeatingMode.REPEAT_ANY_PREVIOUS) }
|
||||
|
||||
fun eval(line: String): LineResult {
|
||||
++lineNumber
|
||||
private val evalState by lazy { scriptEvaluator.createState() }
|
||||
|
||||
fun eval(line: String): ReplEvalResult {
|
||||
|
||||
val fullText = (previousIncompleteLines + line).joinToString(separator = "\n")
|
||||
|
||||
val virtualFile =
|
||||
LightVirtualFile("line$lineNumber${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, fullText).apply {
|
||||
charset = CharsetToolkit.UTF8_CHARSET
|
||||
}
|
||||
val psiFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
|
||||
?: error("Script file not analyzed at line $lineNumber: $fullText")
|
||||
|
||||
val errorHolder = createDiagnosticHolder()
|
||||
|
||||
val syntaxErrorReport = AnalyzerWithCompilerReport.reportSyntaxErrors(psiFile, errorHolder)
|
||||
|
||||
if (syntaxErrorReport.isHasErrors && syntaxErrorReport.isAllErrorsAtEof) {
|
||||
return if (allowIncompleteLines) {
|
||||
previousIncompleteLines.add(line)
|
||||
LineResult.Incomplete
|
||||
}
|
||||
else {
|
||||
LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
previousIncompleteLines.clear()
|
||||
|
||||
if (syntaxErrorReport.isHasErrors) {
|
||||
return LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
|
||||
}
|
||||
|
||||
val analysisResult = analyzerEngine.analyzeReplLine(psiFile, ReplCodeLine(lineNumber, 0, "fake line"))
|
||||
AnalyzerWithCompilerReport.reportDiagnostics(analysisResult.diagnostics, errorHolder)
|
||||
val scriptDescriptor = when (analysisResult) {
|
||||
is ReplCodeAnalyzer.ReplLineAnalysisResult.WithErrors -> return LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
|
||||
is ReplCodeAnalyzer.ReplLineAnalysisResult.Successful -> analysisResult.scriptDescriptor
|
||||
else -> error("Unexpected result ${analysisResult::class.java}")
|
||||
}
|
||||
|
||||
val state = GenerationState(
|
||||
psiFile.project,
|
||||
ClassBuilderFactories.binaries(false),
|
||||
analyzerEngine.module,
|
||||
analyzerEngine.trace.bindingContext,
|
||||
listOf(psiFile),
|
||||
configuration)
|
||||
|
||||
compileScript(psiFile.script!!, earlierLines.map(EarlierLine::getScriptDescriptor), state, CompilationErrorHandler.THROW_EXCEPTION)
|
||||
|
||||
for (outputFile in state.factory.asList()) {
|
||||
if (outputFile.relativePath.endsWith(".class")) {
|
||||
classLoader.addClass(JvmClassName.byInternalName(outputFile.relativePath.replaceFirst("\\.class$".toRegex(), "")),
|
||||
outputFile.asByteArray())
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
val scriptClass = classLoader.loadClass("Line$lineNumber")
|
||||
|
||||
val constructorParams = earlierLines.map(EarlierLine::getScriptClass).toTypedArray()
|
||||
val constructorArgs = earlierLines.map(EarlierLine::getScriptInstance).toTypedArray()
|
||||
val evalRes = scriptEvaluator.compileAndEval(evalState, ReplCodeLine(lineNumber.getAndIncrement(), 0, fullText), null, object : InvokeWrapper {
|
||||
override fun <T> invoke(body: () -> T): T = executeUserCode { body() }
|
||||
})
|
||||
|
||||
val scriptInstanceConstructor = scriptClass.getConstructor(*constructorParams)
|
||||
val scriptInstance = try {
|
||||
executeUserCode { scriptInstanceConstructor.newInstance(*constructorArgs) }
|
||||
when {
|
||||
evalRes !is ReplEvalResult.Incomplete -> previousIncompleteLines.clear()
|
||||
allowIncompleteLines -> previousIncompleteLines.add(line)
|
||||
else -> return ReplEvalResult.Error.CompileTime("incomplete code")
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
// ignore everything in the stack trace until this constructor call
|
||||
return LineResult.Error.Runtime(renderStackTrace(e.cause!!, startFromMethodName = "${scriptClass.name}.<init>"))
|
||||
}
|
||||
|
||||
val rvField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME).apply { isAccessible = true }
|
||||
val rv: Any? = rvField.get(scriptInstance)
|
||||
|
||||
earlierLines.add(EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance))
|
||||
|
||||
if (!state.replSpecific.hasResult) {
|
||||
return LineResult.UnitResult
|
||||
}
|
||||
val valueAsString: String = try {
|
||||
executeUserCode { rv.toString() }
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
return LineResult.Error.Runtime(renderStackTrace(e, startFromMethodName = "java.lang.String.valueOf"))
|
||||
}
|
||||
return LineResult.ValueResult(valueAsString)
|
||||
return evalRes
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
val writer = PrintWriter(System.err)
|
||||
@@ -177,59 +114,8 @@ class ReplInterpreter(
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SCRIPT_RESULT_FIELD_NAME = "\$\$result"
|
||||
private val REPL_LINE_AS_SCRIPT_DEFINITION = object : KotlinScriptDefinition(Any::class) {
|
||||
override val name = "Kotlin REPL"
|
||||
}
|
||||
|
||||
private fun renderStackTrace(cause: Throwable, startFromMethodName: String): String {
|
||||
val newTrace = arrayListOf<StackTraceElement>()
|
||||
var skip = true
|
||||
for (element in cause.stackTrace.reversed()) {
|
||||
if ("${element.className}.${element.methodName}" == startFromMethodName) {
|
||||
skip = false
|
||||
}
|
||||
if (!skip) {
|
||||
newTrace.add(element)
|
||||
}
|
||||
}
|
||||
|
||||
val resultingTrace = newTrace.reversed().dropLast(1)
|
||||
|
||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UsePropertyAccessSyntax")
|
||||
(cause as java.lang.Throwable).setStackTrace(resultingTrace.toTypedArray())
|
||||
|
||||
return Throwables.getStackTraceAsString(cause)
|
||||
}
|
||||
|
||||
fun compileScript(
|
||||
script: KtScript,
|
||||
earlierScripts: List<ScriptDescriptor>,
|
||||
state: GenerationState,
|
||||
errorHandler: CompilationErrorHandler
|
||||
) {
|
||||
state.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME
|
||||
state.replSpecific.earlierScriptsForReplInterpreter = earlierScripts.toList()
|
||||
|
||||
state.beforeCompile()
|
||||
KotlinCodegenFacade.generatePackage(
|
||||
state,
|
||||
script.containingKtFile.packageFqName,
|
||||
setOf(script.containingKtFile),
|
||||
errorHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class LineResult {
|
||||
class ValueResult(val valueAsString: String): LineResult()
|
||||
|
||||
object UnitResult: LineResult()
|
||||
object Incomplete : LineResult()
|
||||
|
||||
sealed class Error(val errorText: String): LineResult() {
|
||||
class Runtime(errorText: String): Error(errorText)
|
||||
class CompileTime(errorText: String): Error(errorText)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
|
||||
environment: Env,
|
||||
daemonOptions: DaemonOptions = configureDaemonOptions()
|
||||
): CompileServiceSession? {
|
||||
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
|
||||
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritOtherJvmOptions = false, inheritAdditionalProperties = true)
|
||||
|
||||
val daemonReportMessages = ArrayList<DaemonReportMessage>()
|
||||
val daemonReportingTargets = DaemonReportingTargets(messages = daemonReportMessages)
|
||||
|
||||
@@ -102,7 +102,7 @@ object KotlinCompilerClient {
|
||||
autostart: Boolean,
|
||||
leaseSession: Boolean,
|
||||
sessionAliveFlagFile: File? = null
|
||||
): CompileServiceSession? = connectLoop(reportingTargets) {
|
||||
): CompileServiceSession? = connectLoop(reportingTargets, autostart) { isLastAttempt ->
|
||||
ensureServerHostnameIsSetUp()
|
||||
val (service, newJVMOptions) = tryFindSuitableDaemonOrNewOpts(File(daemonOptions.runFilesPath), compilerId, daemonJVMOptions, { cat, msg -> reportingTargets.report(cat, msg) })
|
||||
if (service != null) {
|
||||
@@ -119,7 +119,7 @@ object KotlinCompilerClient {
|
||||
}
|
||||
} else {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "no suitable daemon found")
|
||||
if (autostart) {
|
||||
if (!isLastAttempt && autostart) {
|
||||
startDaemon(compilerId, newJVMOptions, daemonOptions, reportingTargets)
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "new daemon started, trying to find it")
|
||||
}
|
||||
@@ -145,6 +145,7 @@ object KotlinCompilerClient {
|
||||
compilerService.releaseCompileSession(sessionId)
|
||||
}
|
||||
|
||||
@Deprecated("Use other compile method", ReplaceWith("compile"))
|
||||
fun compile(compilerService: CompileService,
|
||||
sessionId: Int,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
@@ -158,6 +159,7 @@ object KotlinCompilerClient {
|
||||
}
|
||||
|
||||
|
||||
@Deprecated("Use non-deprecated compile method", ReplaceWith("compile"))
|
||||
fun incrementalCompile(compileService: CompileService,
|
||||
sessionId: Int,
|
||||
targetPlatform: CompileService.TargetPlatform,
|
||||
@@ -234,7 +236,7 @@ object KotlinCompilerClient {
|
||||
fun main(vararg args: String) {
|
||||
val compilerId = CompilerId()
|
||||
val daemonOptions = configureDaemonOptions()
|
||||
val daemonLaunchingOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
|
||||
val daemonLaunchingOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritOtherJvmOptions = false, inheritAdditionalProperties = true)
|
||||
val clientOptions = configureClientOptions()
|
||||
val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX)
|
||||
|
||||
@@ -308,24 +310,27 @@ object KotlinCompilerClient {
|
||||
|
||||
// --- Implementation ---------------------------------------
|
||||
|
||||
private inline fun <R> connectLoop(reportingTargets: DaemonReportingTargets, body: () -> R?): R? {
|
||||
@Synchronized
|
||||
private inline fun <R> connectLoop(reportingTargets: DaemonReportingTargets, autostart: Boolean, body: (Boolean) -> R?): R? {
|
||||
try {
|
||||
var attempts = 0
|
||||
while (attempts < DAEMON_CONNECT_CYCLE_ATTEMPTS) {
|
||||
attempts += 1
|
||||
var attempts = 1
|
||||
while (true) {
|
||||
val (res, err) = try {
|
||||
body() to null
|
||||
body(attempts >= DAEMON_CONNECT_CYCLE_ATTEMPTS) to null
|
||||
}
|
||||
catch (e: SocketException) { null to e }
|
||||
catch (e: ConnectException) { null to e }
|
||||
catch (e: ConnectIOException) { null to e }
|
||||
catch (e: UnmarshalException) { null to e }
|
||||
|
||||
when {
|
||||
res != null -> return res
|
||||
err != null && attempts >= DAEMON_CONNECT_CYCLE_ATTEMPTS -> throw err
|
||||
err != null ->
|
||||
reportingTargets.report(DaemonReportCategory.INFO, "retrying($attempts) on: " + err.toString())
|
||||
if (res != null) return res
|
||||
|
||||
reportingTargets.report(DaemonReportCategory.INFO,
|
||||
(if (attempts >= DAEMON_CONNECT_CYCLE_ATTEMPTS || !autostart) "no more retries on: " else "retrying($attempts) on: ")
|
||||
+ err?.toString())
|
||||
|
||||
if (attempts++ > DAEMON_CONNECT_CYCLE_ATTEMPTS || !autostart) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -335,26 +340,6 @@ object KotlinCompilerClient {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun DaemonReportingTargets.report(category: DaemonReportCategory, message: String, source: String = "daemon client") {
|
||||
if (category == DaemonReportCategory.DEBUG && !verboseReporting) return
|
||||
out?.println("[$source] ${category.name}: $message")
|
||||
messages?.add(DaemonReportMessage(category, "[$source] $message"))
|
||||
messageCollector?.let {
|
||||
when (category) {
|
||||
DaemonReportCategory.DEBUG -> it.report(CompilerMessageSeverity.LOGGING, message)
|
||||
DaemonReportCategory.INFO -> it.report(CompilerMessageSeverity.INFO, message)
|
||||
DaemonReportCategory.EXCEPTION -> it.report(CompilerMessageSeverity.EXCEPTION, message)
|
||||
}
|
||||
}
|
||||
compilerServices?.let {
|
||||
when (category) {
|
||||
DaemonReportCategory.DEBUG -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.DEBUG, message, source)
|
||||
DaemonReportCategory.INFO -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.INFO, message, source)
|
||||
DaemonReportCategory.EXCEPTION -> it.report(ReportCategory.EXCEPTION, ReportSeverity.ERROR, message, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryFindSuitableDaemonOrNewOpts(registryDir: File, compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, report: (DaemonReportCategory, String) -> Unit): Pair<CompileService?, DaemonJVMOptions> {
|
||||
registryDir.mkdirs()
|
||||
val timestampMarker = createTempFile("kotlin-daemon-client-tsmarker", directory = registryDir)
|
||||
@@ -364,7 +349,7 @@ object KotlinCompilerClient {
|
||||
finally {
|
||||
timestampMarker.delete()
|
||||
}
|
||||
val comparator = compareByDescending<DaemonWithMetadata, DaemonJVMOptions>(DaemonJVMOptionsMemoryComparator(), { it.jvmOptions })
|
||||
val comparator = compareBy<DaemonWithMetadata, DaemonJVMOptions>(DaemonJVMOptionsMemoryComparator(), { it.jvmOptions })
|
||||
.thenBy(FileAgeComparator()) { it.runFile }
|
||||
val optsCopy = daemonJVMOptions.copy()
|
||||
// if required options fit into fattest running daemon - return the daemon and required options with memory params set to actual ones in the daemon
|
||||
@@ -395,19 +380,7 @@ object KotlinCompilerClient {
|
||||
val processBuilder = ProcessBuilder(args)
|
||||
processBuilder.redirectErrorStream(true)
|
||||
// assuming daemon process is deaf and (mostly) silent, so do not handle streams
|
||||
val daemon =
|
||||
try {
|
||||
launchWithNativePlatformLauncher(processBuilder)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "Could not start daemon with native process launcher, falling back to ProcessBuilder#start (${e.cause})")
|
||||
null
|
||||
}
|
||||
catch (e: NoClassDefFoundError) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "net.rubygrapefruit.platform library is not in the classpath, falling back to ProcessBuilder#start")
|
||||
null
|
||||
}
|
||||
?: processBuilder.start()
|
||||
val daemon = launchProcessWithFallback(processBuilder, reportingTargets, "daemon client")
|
||||
|
||||
val isEchoRead = Semaphore(1)
|
||||
isEchoRead.acquire()
|
||||
@@ -418,19 +391,21 @@ object KotlinCompilerClient {
|
||||
daemon.inputStream
|
||||
.reader()
|
||||
.forEachLine {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, it, "daemon")
|
||||
|
||||
if (it == COMPILE_DAEMON_IS_READY_MESSAGE) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "Received the message signalling that the daemon is ready")
|
||||
isEchoRead.release()
|
||||
return@forEachLine
|
||||
}
|
||||
else {
|
||||
reportingTargets.report(DaemonReportCategory.INFO, it, "daemon")
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
daemon.inputStream.close()
|
||||
daemon.outputStream.close()
|
||||
daemon.errorStream.close()
|
||||
isEchoRead.release()
|
||||
}
|
||||
}
|
||||
try {
|
||||
@@ -474,6 +449,25 @@ class DaemonReportingTargets(val out: PrintStream? = null,
|
||||
val messageCollector: MessageCollector? = null,
|
||||
val compilerServices: CompilerServicesFacadeBase? = null)
|
||||
|
||||
internal fun DaemonReportingTargets.report(category: DaemonReportCategory, message: String, source: String? = null) {
|
||||
val sourceMessage: String by lazy { source?.let { "[$it] $message" } ?: message }
|
||||
out?.println("${category.name}: $sourceMessage")
|
||||
messages?.add(DaemonReportMessage(category, sourceMessage))
|
||||
messageCollector?.let {
|
||||
when (category) {
|
||||
DaemonReportCategory.DEBUG -> it.report(CompilerMessageSeverity.LOGGING, sourceMessage)
|
||||
DaemonReportCategory.INFO -> it.report(CompilerMessageSeverity.INFO, sourceMessage)
|
||||
DaemonReportCategory.EXCEPTION -> it.report(CompilerMessageSeverity.EXCEPTION, sourceMessage)
|
||||
}
|
||||
}
|
||||
compilerServices?.let {
|
||||
when (category) {
|
||||
DaemonReportCategory.DEBUG -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.DEBUG, message, source)
|
||||
DaemonReportCategory.INFO -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.INFO, message, source)
|
||||
DaemonReportCategory.EXCEPTION -> it.report(ReportCategory.EXCEPTION, ReportSeverity.ERROR, message, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun isProcessAlive(process: Process) =
|
||||
try {
|
||||
|
||||
@@ -16,17 +16,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.daemon.client
|
||||
|
||||
import net.rubygrapefruit.platform.Native
|
||||
import net.rubygrapefruit.platform.NativeException
|
||||
import net.rubygrapefruit.platform.ProcessLauncher
|
||||
import org.jetbrains.kotlin.daemon.common.DaemonReportCategory
|
||||
import java.io.IOException
|
||||
|
||||
internal fun launchWithNativePlatformLauncher(processBuilder: ProcessBuilder): Process {
|
||||
return try {
|
||||
val nativeLauncher = Native.get(ProcessLauncher::class.java)
|
||||
nativeLauncher.start(processBuilder)
|
||||
}
|
||||
catch (e: NativeException) {
|
||||
throw IOException(e)
|
||||
}
|
||||
}
|
||||
private class NativePlatformLauncherWrapper {
|
||||
fun launch(processBuilder: ProcessBuilder): Process =
|
||||
try {
|
||||
val nativeLauncher = net.rubygrapefruit.platform.Native.get(net.rubygrapefruit.platform.ProcessLauncher::class.java)
|
||||
nativeLauncher.start(processBuilder)
|
||||
}
|
||||
catch (e: net.rubygrapefruit.platform.NativeException) {
|
||||
throw IOException(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun launchProcessWithFallback(processBuilder: ProcessBuilder, reportingTargets: DaemonReportingTargets, reportingSource: String = "process launcher"): Process =
|
||||
try {
|
||||
NativePlatformLauncherWrapper().launch(processBuilder)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "Could not start process with native process launcher, falling back to ProcessBuilder#start (${e.cause})")
|
||||
null
|
||||
}
|
||||
catch (e: NoClassDefFoundError) {
|
||||
reportingTargets.report(DaemonReportCategory.DEBUG, "net.rubygrapefruit.platform library is not in the classpath, falling back to ProcessBuilder#start")
|
||||
null
|
||||
}
|
||||
?: processBuilder.start()
|
||||
|
||||
@@ -37,10 +37,12 @@ class RemoteReplCompilerStateHistory(private val state: RemoteReplCompilerState)
|
||||
throw NotImplementedError("pop from remote history is not supported")
|
||||
}
|
||||
|
||||
override fun reset(): Iterable<ILineId> = state.replStateFacade.historyReset().apply {
|
||||
currentGeneration.incrementAndGet()
|
||||
}
|
||||
|
||||
override fun resetTo(id: ILineId): Iterable<ILineId> = state.replStateFacade.historyResetTo(id).apply {
|
||||
if (isNotEmpty()) {
|
||||
currentGeneration.incrementAndGet()
|
||||
}
|
||||
currentGeneration.incrementAndGet()
|
||||
}
|
||||
|
||||
val currentGeneration = AtomicInteger(REPL_CODE_LINE_FIRST_GEN)
|
||||
|
||||
@@ -44,6 +44,10 @@ private const val ORPHANED_RUN_FILE_AGE_THRESHOLD_MS = 1000000L
|
||||
|
||||
data class DaemonWithMetadata(val daemon: CompileService, val runFile: File, val jvmOptions: DaemonJVMOptions)
|
||||
|
||||
// TODO: write metadata into discovery file to speed up selection
|
||||
// TODO: consider using compiler jar signature (checksum) as a CompilerID (plus java version, plus ???) instead of classpath checksum
|
||||
// would allow to use same compiler from taken different locations
|
||||
// reqs: check that plugins (or anything els) should not be part of the CP
|
||||
fun walkDaemons(registryDir: File,
|
||||
compilerId: CompilerId,
|
||||
fileToCompareTimestamp: File,
|
||||
|
||||
@@ -257,15 +257,44 @@ data class CompilerId(
|
||||
|
||||
fun isDaemonEnabled(): Boolean = System.getProperty(COMPILE_DAEMON_ENABLED_PROPERTY) != null
|
||||
|
||||
|
||||
fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
|
||||
vararg additionalParams: String,
|
||||
inheritMemoryLimits: Boolean,
|
||||
inheritOtherJvmOptions: Boolean,
|
||||
inheritAdditionalProperties: Boolean
|
||||
): DaemonJVMOptions =
|
||||
configureDaemonJVMOptions(opts, additionalParams.asIterable(), inheritMemoryLimits, inheritOtherJvmOptions, inheritAdditionalProperties)
|
||||
|
||||
// TODO: expose sources for testability and test properly
|
||||
fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
|
||||
additionalParams: Iterable<String>,
|
||||
inheritMemoryLimits: Boolean,
|
||||
inheritOtherJvmOptions: Boolean,
|
||||
inheritAdditionalProperties: Boolean
|
||||
): DaemonJVMOptions {
|
||||
// note: sequence matters, explicit override in COMPILE_DAEMON_JVM_OPTIONS_PROPERTY should be done after inputArguments processing
|
||||
if (inheritMemoryLimits) {
|
||||
ManagementFactory.getRuntimeMXBean().inputArguments.filterExtractProps(opts.mappers, "-")
|
||||
// note: sequence matters, e.g. explicit override in COMPILE_DAEMON_JVM_OPTIONS_PROPERTY should be done after inputArguments processing
|
||||
if (inheritMemoryLimits || inheritOtherJvmOptions) {
|
||||
val jvmArguments = ManagementFactory.getRuntimeMXBean().inputArguments
|
||||
val targetOptions = if (inheritMemoryLimits) opts else DaemonJVMOptions()
|
||||
val otherArgs = jvmArguments.filterExtractProps(targetOptions.mappers, prefix = "-")
|
||||
|
||||
if (inheritMemoryLimits && opts.maxMemory.isBlank()) {
|
||||
val maxMemBytes = Runtime.getRuntime().maxMemory()
|
||||
// rounding up
|
||||
val maxMemMegabytes = maxMemBytes / (1024 * 1024) + if (maxMemBytes % (1024 * 1024) == 0L) 0 else 1
|
||||
opts.maxMemory = "${maxMemMegabytes}m"
|
||||
}
|
||||
|
||||
if (inheritOtherJvmOptions) {
|
||||
opts.jvmParams.addAll(
|
||||
otherArgs.filterNot {
|
||||
it.startsWith("agentlib") ||
|
||||
it.startsWith("D" + COMPILE_DAEMON_LOG_PATH_PROPERTY) ||
|
||||
it.startsWith("D" + KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY) ||
|
||||
it.startsWith("D" + COMPILE_DAEMON_JVM_OPTIONS_PROPERTY) ||
|
||||
it.startsWith("D" + COMPILE_DAEMON_OPTIONS_PROPERTY)
|
||||
})
|
||||
}
|
||||
}
|
||||
System.getProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY)?.let {
|
||||
opts.jvmParams.addAll(
|
||||
@@ -275,7 +304,10 @@ fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
|
||||
.filterExtractProps(opts.mappers, "-", opts.restMapper))
|
||||
}
|
||||
|
||||
// assuming that from the conflicting options the last one is taken
|
||||
// TODO: compare and override
|
||||
opts.jvmParams.addAll(additionalParams)
|
||||
|
||||
if (inheritAdditionalProperties) {
|
||||
System.getProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY)?.let { opts.jvmParams.add("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"$it\"") }
|
||||
System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY)?.let { opts.jvmParams.add("D$KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY") }
|
||||
@@ -285,12 +317,14 @@ fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
|
||||
|
||||
|
||||
fun configureDaemonJVMOptions(vararg additionalParams: String,
|
||||
inheritMemoryLimits: Boolean,
|
||||
inheritAdditionalProperties: Boolean
|
||||
inheritMemoryLimits: Boolean,
|
||||
inheritOtherJvmOptions: Boolean,
|
||||
inheritAdditionalProperties: Boolean
|
||||
): DaemonJVMOptions =
|
||||
configureDaemonJVMOptions(DaemonJVMOptions(),
|
||||
additionalParams = *additionalParams,
|
||||
inheritMemoryLimits = inheritMemoryLimits,
|
||||
inheritOtherJvmOptions = inheritOtherJvmOptions,
|
||||
inheritAdditionalProperties = inheritAdditionalProperties)
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ interface ReplStateFacade : Remote {
|
||||
@Throws(RemoteException::class)
|
||||
fun historyGet(index: Int): ILineId
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun historyReset(): List<ILineId>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun historyResetTo(id: ILineId): List<ILineId>
|
||||
}
|
||||
@@ -107,6 +107,8 @@ class CompileServiceImpl(
|
||||
val onShutdown: () -> Unit
|
||||
) : CompileService {
|
||||
|
||||
private val log by lazy { Logger.getLogger("compiler") }
|
||||
|
||||
init {
|
||||
System.setProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true")
|
||||
}
|
||||
@@ -184,8 +186,6 @@ class CompileServiceImpl(
|
||||
@Volatile private var _lastUsedSeconds = nowSeconds()
|
||||
val lastUsedSeconds: Long get() = if (rwlock.isWriteLocked || rwlock.readLockCount - rwlock.readHoldCount > 0) nowSeconds() else _lastUsedSeconds
|
||||
|
||||
private val log by lazy { Logger.getLogger("compiler") }
|
||||
|
||||
private val rwlock = ReentrantReadWriteLock()
|
||||
|
||||
private var runFile: File
|
||||
@@ -212,12 +212,15 @@ class CompileServiceImpl(
|
||||
}
|
||||
|
||||
override fun getDaemonJVMOptions(): CompileService.CallResult<DaemonJVMOptions> = ifAlive {
|
||||
log.info("getDaemonJVMOptions: $daemonJVMOptions")// + daemonJVMOptions.mappers.flatMap { it.toArgs("-") })
|
||||
|
||||
CompileService.CallResult.Good(daemonJVMOptions)
|
||||
}
|
||||
|
||||
override fun registerClient(aliveFlagPath: String?): CompileService.CallResult<Nothing> = ifAlive {
|
||||
synchronized(state.clientProxies) {
|
||||
state.clientProxies.add(ClientOrSessionProxy(aliveFlagPath))
|
||||
log.info("Registered a client alive file: $aliveFlagPath")
|
||||
}
|
||||
CompileService.CallResult.Ok()
|
||||
}
|
||||
@@ -232,7 +235,7 @@ class CompileServiceImpl(
|
||||
override fun leaseCompileSession(aliveFlagPath: String?): CompileService.CallResult<Int> = ifAlive(minAliveness = Aliveness.Alive) {
|
||||
CompileService.CallResult.Good(
|
||||
state.sessions.leaseSession(ClientOrSessionProxy<Any>(aliveFlagPath)).apply {
|
||||
log.info("leased a new session $this, client alive file: $aliveFlagPath")
|
||||
log.info("leased a new session $this, session alive file: $aliveFlagPath")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -335,6 +338,7 @@ class CompileServiceImpl(
|
||||
val daemonReporter = DaemonMessageReporter(servicesFacade, compilationOptions)
|
||||
val compilerMode = compilationOptions.compilerMode
|
||||
val targetPlatform = compilationOptions.targetPlatform
|
||||
log.info("Starting compilation with args: " + compilerArguments.joinToString(" "))
|
||||
val k2PlatformArgs = try {
|
||||
when (targetPlatform) {
|
||||
CompileService.TargetPlatform.JVM -> K2JVMCompilerArguments().apply { K2JVMCompiler().parseArguments(compilerArguments, this) }
|
||||
@@ -709,6 +713,10 @@ class CompileServiceImpl(
|
||||
|
||||
private fun shutdownImpl() {
|
||||
log.info("Shutdown started")
|
||||
fun Long.mb() = this / (1024 * 1024)
|
||||
with (Runtime.getRuntime()) {
|
||||
log.info("Memory stats: total: ${totalMemory().mb()}mb, free: ${freeMemory().mb()}mb, max: ${maxMemory().mb()}mb")
|
||||
}
|
||||
state.alive.set(Aliveness.Dying.ordinal)
|
||||
|
||||
UnicastRemoteObject.unexportObject(this, true)
|
||||
@@ -869,9 +877,18 @@ class CompileServiceImpl(
|
||||
ifAliveChecksImpl(minAliveness, ignoreCompilerChanged, body)
|
||||
}
|
||||
|
||||
inline private fun<R> ifAliveChecksImpl(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> CompileService.CallResult<R>): CompileService.CallResult<R> =
|
||||
when {
|
||||
state.alive.get() < minAliveness.ordinal -> CompileService.CallResult.Dying()
|
||||
inline private fun<R> ifAliveChecksImpl(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> CompileService.CallResult<R>): CompileService.CallResult<R> {
|
||||
val curState = state.alive.get()
|
||||
return when {
|
||||
curState < minAliveness.ordinal -> {
|
||||
log.info("Cannot perform operation, requested state: ${minAliveness.name} > actual: ${try {
|
||||
Aliveness.values()[curState].name
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
"invalid($curState)"
|
||||
}}")
|
||||
CompileService.CallResult.Dying()
|
||||
}
|
||||
!ignoreCompilerChanged && classpathWatcher.isChanged -> {
|
||||
log.info("Compiler changed, scheduling shutdown")
|
||||
shutdownWithDelay()
|
||||
@@ -887,6 +904,7 @@ class CompileServiceImpl(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun<R> withValidClientOrSessionProxy(sessionId: Int,
|
||||
body: (ClientOrSessionProxy<Any>?) -> CompileService.CallResult<R>
|
||||
|
||||
@@ -91,8 +91,10 @@ object KotlinCompileDaemon {
|
||||
fun main(args: Array<String>) {
|
||||
ensureServerHostnameIsSetUp()
|
||||
|
||||
val jvmArguments = ManagementFactory.getRuntimeMXBean().inputArguments
|
||||
|
||||
log.info("Kotlin compiler daemon version " + (loadVersionFromResource() ?: "<unknown>"))
|
||||
log.info("daemon JVM args: " + ManagementFactory.getRuntimeMXBean().inputArguments.joinToString(" "))
|
||||
log.info("daemon JVM args: " + jvmArguments.joinToString(" "))
|
||||
log.info("daemon args: " + args.joinToString(" "))
|
||||
|
||||
setIdeaIoUseFallback()
|
||||
@@ -101,7 +103,9 @@ object KotlinCompileDaemon {
|
||||
val daemonOptions = DaemonOptions()
|
||||
|
||||
try {
|
||||
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
|
||||
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true,
|
||||
inheritOtherJvmOptions = true,
|
||||
inheritAdditionalProperties = true)
|
||||
|
||||
val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX)
|
||||
|
||||
|
||||
@@ -35,5 +35,7 @@ class RemoteReplStateFacadeServer(val _id: Int,
|
||||
|
||||
override fun historyGet(index: Int): ILineId = state.history[index].id
|
||||
|
||||
override fun historyReset(): List<ILineId> = state.history.reset().toList()
|
||||
|
||||
override fun historyResetTo(id: ILineId): List<ILineId> = state.history.resetTo(id).toList()
|
||||
}
|
||||
|
||||
@@ -129,12 +129,16 @@ public class SingleAbstractMethodUtils {
|
||||
|
||||
@Nullable
|
||||
public static FunctionDescriptor getSingleAbstractMethodOrNull(@NotNull JavaClassDescriptor klass) {
|
||||
if (klass.isDefinitelyNotSamInterface()) return null;
|
||||
|
||||
// NB: this check MUST BE at start. Please do not touch until following to-do is resolved
|
||||
// Otherwise android data binding can cause resolve re-entrance
|
||||
// For details see KT-18687, KT-16149
|
||||
// TODO: prevent resolve re-entrance on architecture level, or (alternatively) ask data binding owners not to do it
|
||||
if (DescriptorUtilsKt.getFqNameSafe(klass).asString().equals("android.databinding.DataBindingComponent")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (klass.isDefinitelyNotSamInterface()) return null;
|
||||
|
||||
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass.getDefaultType());
|
||||
if (abstractMembers.size() == 1) {
|
||||
CallableMemberDescriptor member = abstractMembers.get(0);
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedTypeAliasDescriptor
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
|
||||
interface ModuleVisibilityManager {
|
||||
val chunk: Collection<Module>
|
||||
@@ -66,24 +67,25 @@ fun isContainedByCompiledPartOfOurModule(descriptor: DeclarationDescriptor, outD
|
||||
|
||||
if (binaryClass is VirtualFileKotlinClass) {
|
||||
val file = binaryClass.file
|
||||
if (file.fileSystem.protocol == StandardFileSystems.FILE_PROTOCOL) {
|
||||
val ioFile = VfsUtilCore.virtualToIoFile(file)
|
||||
return ioFile.absolutePath.startsWith(outDirectory.absolutePath + File.separator)
|
||||
val ioFile = when (file.fileSystem.protocol) {
|
||||
StandardFileSystems.FILE_PROTOCOL -> VfsUtilCore.virtualToIoFile(file)
|
||||
StandardFileSystems.JAR_PROTOCOL -> VfsUtilCore.getVirtualFileForJar(file)?.let(VfsUtilCore::virtualToIoFile)
|
||||
else -> null
|
||||
}
|
||||
return ioFile != null && Paths.get(ioFile.toURI()).startsWith(Paths.get(outDirectory.toURI()))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun getSourceElement(descriptor: DeclarationDescriptor): SourceElement =
|
||||
if (descriptor is CallableMemberDescriptor && descriptor.source === SourceElement.NO_SOURCE) {
|
||||
descriptor.containingDeclaration.toSourceElement
|
||||
}
|
||||
else if (descriptor is DeserializedTypeAliasDescriptor) {
|
||||
descriptor.containingDeclaration.toSourceElement
|
||||
}
|
||||
else {
|
||||
descriptor.toSourceElement
|
||||
when {
|
||||
descriptor is CallableMemberDescriptor && descriptor.source === SourceElement.NO_SOURCE ->
|
||||
getSourceElement(descriptor.containingDeclaration)
|
||||
descriptor is DeserializedTypeAliasDescriptor ->
|
||||
getSourceElement(descriptor.containingDeclaration)
|
||||
else ->
|
||||
descriptor.toSourceElement
|
||||
}
|
||||
|
||||
private val DeclarationDescriptor.toSourceElement: SourceElement
|
||||
|
||||
@@ -55,7 +55,7 @@ object JvmOverridesBackwardCompatibilityHelper : OverridesBackwardCompatibilityH
|
||||
val containingClass = DescriptorUtils.getContainingClass(overriddenDescriptor)
|
||||
?: return false
|
||||
|
||||
if (JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(containingClass.fqNameUnsafe) != null) return true
|
||||
if (JavaToKotlinClassMap.mapKotlinToJava(containingClass.fqNameUnsafe) != null) return true
|
||||
if (overriddenDescriptor.overriddenDescriptors.isEmpty()) return false
|
||||
|
||||
return isOverridingOnlyDescriptorsThatCanBeImplicitlyOverridden(overriddenDescriptor, visitedDescriptors)
|
||||
|
||||
@@ -39,7 +39,9 @@ enum class JvmDeclarationOriginKind {
|
||||
BRIDGE,
|
||||
MULTIFILE_CLASS,
|
||||
MULTIFILE_CLASS_PART,
|
||||
SYNTHETIC // this means that there's no proper descriptor for this jvm declaration
|
||||
SYNTHETIC, // this means that there's no proper descriptor for this jvm declaration,
|
||||
COLLECTION_STUB,
|
||||
AUGMENTED_BUILTIN_API
|
||||
}
|
||||
|
||||
class JvmDeclarationOrigin(
|
||||
@@ -91,3 +93,7 @@ fun Delegation(element: PsiElement?, descriptor: FunctionDescriptor): JvmDeclara
|
||||
fun SamDelegation(descriptor: FunctionDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(SAM_DELEGATION, null, descriptor)
|
||||
|
||||
fun Synthetic(element: PsiElement?, descriptor: CallableMemberDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(SYNTHETIC, element, descriptor)
|
||||
|
||||
val CollectionStub = JvmDeclarationOrigin(COLLECTION_STUB, null, null)
|
||||
|
||||
fun AugmentedBuiltInApi(descriptor: CallableDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(AUGMENTED_BUILTIN_API, null, descriptor)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.modules
|
||||
|
||||
interface JavaModuleFinder {
|
||||
fun findModule(name: String): JavaModuleInfo?
|
||||
}
|
||||
@@ -14,26 +14,29 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.modules
|
||||
package org.jetbrains.kotlin.resolve.jvm.modules
|
||||
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
|
||||
class ModuleGraph(getModuleInfo: (String) -> JavaModuleInfo) {
|
||||
private val moduleInfo: (String) -> JavaModuleInfo = LockBasedStorageManager.NO_LOCKS.createMemoizedFunction(getModuleInfo)
|
||||
class JavaModuleGraph(finder: JavaModuleFinder) {
|
||||
private val moduleInfo: (String) -> JavaModuleInfo? =
|
||||
LockBasedStorageManager.NO_LOCKS.createMemoizedFunctionWithNullableValues(finder::findModule)
|
||||
|
||||
fun getAllReachable(rootModules: List<String>): List<String> {
|
||||
val visited = linkedSetOf<String>()
|
||||
fun getAllDependencies(moduleNames: List<String>): List<String> {
|
||||
// Every module implicitly depends on java.base
|
||||
val visited = linkedSetOf("java.base")
|
||||
|
||||
fun dfs(module: String) {
|
||||
if (!visited.add(module)) return
|
||||
for (dependency in moduleInfo(module).requires) {
|
||||
val moduleInfo = moduleInfo(module) ?: return
|
||||
for (dependency in moduleInfo.requires) {
|
||||
if (dependency.isTransitive) {
|
||||
dfs(dependency.moduleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rootModules.forEach(::dfs)
|
||||
moduleNames.forEach(::dfs)
|
||||
return visited.toList()
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.modules
|
||||
package org.jetbrains.kotlin.resolve.jvm.modules
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -75,7 +75,7 @@ object JvmPlatformConfigurator : PlatformConfigurator(
|
||||
|
||||
overloadFilter = JvmOverloadFilter,
|
||||
|
||||
platformToKotlinClassMap = JavaToKotlinClassMap.INSTANCE,
|
||||
platformToKotlinClassMap = JavaToKotlinClassMap,
|
||||
|
||||
delegationFilter = JvmDelegationFilter,
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import java.io.File
|
||||
import java.lang.management.ManagementFactory
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.read
|
||||
import kotlin.concurrent.write
|
||||
@@ -63,69 +65,85 @@ class KotlinScriptExternalImportsProviderImpl(
|
||||
// optimized for initial caching, additional handling of possible duplicates to save a call to distinct
|
||||
// returns list of cached files
|
||||
override fun <TF: Any> cacheExternalImports(files: Iterable<TF>): Iterable<TF> = cacheLock.write {
|
||||
val uncached = hashSetOf<String>()
|
||||
files.mapNotNull { file ->
|
||||
val path = getFilePath(file)
|
||||
if (isValidFile(file) && !cache.containsKey(path) && !uncached.contains(path)) {
|
||||
var filesCount = 0
|
||||
var additionsCount = 0
|
||||
val (res, time) = measureThreadTimeMillis {
|
||||
files.mapNotNull { file ->
|
||||
filesCount += 1
|
||||
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
|
||||
if (scriptDef != null) {
|
||||
val deps = scriptDef.getDependenciesFor(file, project, null)
|
||||
if (deps != null) {
|
||||
log.info("[kts] cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
|
||||
val path = getFilePath(file)
|
||||
if (isValidFile(file) && !cache.containsKey(path)) {
|
||||
val deps = scriptDef.getDependenciesFor(file, project, null)
|
||||
cache.put(path, deps)
|
||||
if (deps != null) {
|
||||
log.info("[kts] cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
|
||||
additionsCount += 1
|
||||
file
|
||||
}
|
||||
else null
|
||||
}
|
||||
cache.put(path, deps)
|
||||
file
|
||||
}
|
||||
else {
|
||||
uncached.add(path)
|
||||
null
|
||||
else null
|
||||
}
|
||||
else null
|
||||
}
|
||||
else null
|
||||
}
|
||||
log.info("[kts] cache creation: $filesCount checked, $additionsCount added (in ${time}ms)")
|
||||
res
|
||||
}
|
||||
|
||||
// optimized for update, no special duplicates handling
|
||||
// returns files with valid script definition (or deleted from cache - which in fact should have script def too)
|
||||
// TODO: this is the badly designed contract, since it mixes the entities, but these files are needed on the calling site now. Find out other solution
|
||||
override fun <TF: Any> updateExternalImportsCache(files: Iterable<TF>): Iterable<TF> = cacheLock.write {
|
||||
files.mapNotNull { file ->
|
||||
val path = getFilePath(file)
|
||||
if (!isValidFile(file)) {
|
||||
if (cache.remove(path) != null) {
|
||||
log.debug("[kts] removed deps for file $path")
|
||||
file
|
||||
} // cleared
|
||||
else {
|
||||
null // unknown
|
||||
}
|
||||
}
|
||||
else {
|
||||
var filesCount = 0
|
||||
var updatesCount = 0
|
||||
val (res, time) = measureThreadTimeMillis {
|
||||
files.mapNotNull { file ->
|
||||
filesCount += 1
|
||||
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
|
||||
if (scriptDef != null) {
|
||||
val oldDeps = cache[path]
|
||||
val deps = scriptDef.getDependenciesFor(file, project, oldDeps)
|
||||
when {
|
||||
deps != null && (oldDeps == null ||
|
||||
!deps.classpath.isSamePathListAs(oldDeps.classpath) || !deps.sources.isSamePathListAs(oldDeps.sources)) -> {
|
||||
// changed or new
|
||||
log.info("[kts] updated/new cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
|
||||
cache.put(path, deps)
|
||||
}
|
||||
deps != null -> {
|
||||
// same as before
|
||||
}
|
||||
else -> {
|
||||
if (cache.remove(path) != null) {
|
||||
val path = getFilePath(file)
|
||||
if (!isValidFile(file)) {
|
||||
if (cache.remove(path) != null) {
|
||||
log.debug("[kts] removed deps for file $path")
|
||||
updatesCount += 1
|
||||
file
|
||||
} // cleared
|
||||
else null // unknown
|
||||
}
|
||||
else {
|
||||
val oldDeps = cache[path]
|
||||
val deps = scriptDef.getDependenciesFor(file, project, oldDeps)
|
||||
when {
|
||||
deps != null && (oldDeps == null ||
|
||||
!deps.classpath.isSamePathListAs(oldDeps.classpath) || !deps.sources.isSamePathListAs(oldDeps.sources)) -> {
|
||||
// changed or new
|
||||
log.info("[kts] updated/new cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
|
||||
cache.put(path, deps)
|
||||
updatesCount += 1
|
||||
file
|
||||
}
|
||||
deps != null -> {
|
||||
// same as before
|
||||
null
|
||||
}
|
||||
cache.remove(path) != null -> {
|
||||
log.debug("[kts] removed deps for $path")
|
||||
} // cleared
|
||||
updatesCount += 1
|
||||
file
|
||||
}
|
||||
else -> null // unknown
|
||||
}
|
||||
}
|
||||
file
|
||||
}
|
||||
else null // not a script
|
||||
}
|
||||
}
|
||||
if (updatesCount > 0) {
|
||||
log.info("[kts] cache update check: $filesCount checked, $updatesCount updated (in ${time}ms)")
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
override fun invalidateCaches() {
|
||||
@@ -160,3 +178,10 @@ private fun Iterable<File>.isSamePathListAs(other: Iterable<File>): Boolean =
|
||||
}
|
||||
!(first.hasNext() || second.hasNext())
|
||||
}
|
||||
|
||||
private inline fun<T> measureThreadTimeMillis(body: () -> T): Pair<T, Long> {
|
||||
val mxBeans = ManagementFactory.getThreadMXBean()
|
||||
val startTime = mxBeans.currentThreadCpuTime
|
||||
val res = body()
|
||||
return res to TimeUnit.NANOSECONDS.toMillis(mxBeans.currentThreadCpuTime - startTime)
|
||||
}
|
||||
|
||||
@@ -41,13 +41,14 @@ import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.storage.NotNullLazyValue
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import java.util.*
|
||||
import kotlin.coroutines.experimental.buildSequence
|
||||
|
||||
class ResolverForModule(
|
||||
val packageFragmentProvider: PackageFragmentProvider,
|
||||
val componentProvider: ComponentProvider
|
||||
val packageFragmentProvider: PackageFragmentProvider,
|
||||
val componentProvider: ComponentProvider
|
||||
)
|
||||
|
||||
abstract class ResolverForProject<M : ModuleInfo> {
|
||||
@@ -84,7 +85,7 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
||||
return resolverForModuleDescriptor(doGetDescriptorForModule(moduleInfo))
|
||||
}
|
||||
|
||||
internal val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, () -> ResolverForModule> = HashMap()
|
||||
internal val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, NotNullLazyValue<ResolverForModule>> = HashMap()
|
||||
|
||||
override val allModules: Collection<M> by lazy {
|
||||
(descriptorByModule.keys + delegateResolver.allModules).toSet()
|
||||
@@ -168,7 +169,8 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
||||
delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
|
||||
packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty },
|
||||
firstDependency: M? = null,
|
||||
modulePlatforms: (M) -> MultiTargetPlatform?
|
||||
modulePlatforms: (M) -> MultiTargetPlatform?,
|
||||
packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory
|
||||
): ResolverForProject<M> {
|
||||
val storageManager = projectContext.storageManager
|
||||
|
||||
@@ -212,8 +214,10 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
||||
|
||||
for (module in modules) {
|
||||
val descriptor = resolverForProject.descriptorForModule(module)
|
||||
val content = modulesContent(module)
|
||||
val computeResolverForModule = storageManager.createLazyValue {
|
||||
val content = modulesContent(module)
|
||||
ResolverForModuleComputationTracker.getInstance(projectContext.project)?.onResolverComputed(module)
|
||||
|
||||
analyzerFacade(module).createResolverForModule(
|
||||
module, descriptor, projectContext.withModule(descriptor), modulesContent(module),
|
||||
platformParameters, targetEnvironment, resolverForProject,
|
||||
@@ -221,7 +225,9 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
||||
)
|
||||
}
|
||||
|
||||
descriptor.initialize(DelegatingPackageFragmentProvider { computeResolverForModule().packageFragmentProvider })
|
||||
DelegatingPackageFragmentProvider(content, packageOracleFactory.createOracle(module), computeResolverForModule)
|
||||
.let { descriptor.initialize(it) }
|
||||
|
||||
resolverForProject.resolverByModuleDescriptor[descriptor] = computeResolverForModule
|
||||
}
|
||||
|
||||
@@ -243,17 +249,45 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
||||
abstract val targetPlatform: TargetPlatform
|
||||
}
|
||||
|
||||
//NOTE: relies on delegate to be lazily computed and cached
|
||||
private class DelegatingPackageFragmentProvider(
|
||||
private val delegate: () -> PackageFragmentProvider
|
||||
moduleContent: ModuleContent,
|
||||
private val packageOracle: PackageOracle,
|
||||
private val resolverForModule: NotNullLazyValue<ResolverForModule>
|
||||
) : PackageFragmentProvider {
|
||||
private val syntheticFilePackages = moduleContent.syntheticFiles.map { it.packageFqName }.toSet()
|
||||
|
||||
override fun getPackageFragments(fqName: FqName): List<PackageFragmentDescriptor> {
|
||||
return delegate().getPackageFragments(fqName)
|
||||
if (certainlyDoesNotExist(fqName)) return emptyList()
|
||||
|
||||
return resolverForModule().packageFragmentProvider.getPackageFragments(fqName)
|
||||
}
|
||||
|
||||
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
|
||||
return delegate().getSubPackagesOf(fqName, nameFilter)
|
||||
if (certainlyDoesNotExist(fqName)) return emptyList()
|
||||
|
||||
return resolverForModule().packageFragmentProvider.getSubPackagesOf(fqName, nameFilter)
|
||||
}
|
||||
|
||||
private fun certainlyDoesNotExist(fqName: FqName): Boolean {
|
||||
if (resolverForModule.isComputed()) return false // let this request get cached inside delegate
|
||||
|
||||
return !packageOracle.packageExists(fqName) && fqName !in syntheticFilePackages
|
||||
}
|
||||
}
|
||||
|
||||
interface PackageOracle {
|
||||
fun packageExists(fqName: FqName): Boolean
|
||||
|
||||
object Optimistic : PackageOracle {
|
||||
override fun packageExists(fqName: FqName): Boolean = true
|
||||
}
|
||||
}
|
||||
|
||||
interface PackageOracleFactory {
|
||||
fun createOracle(moduleInfo: ModuleInfo): PackageOracle
|
||||
|
||||
object OptimisticFactory : PackageOracleFactory {
|
||||
override fun createOracle(moduleInfo: ModuleInfo) = PackageOracle.Optimistic
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,4 +305,13 @@ interface LanguageSettingsProvider {
|
||||
companion object {
|
||||
fun getInstance(project: Project) = ServiceManager.getService(project, LanguageSettingsProvider::class.java) ?: Default
|
||||
}
|
||||
}
|
||||
|
||||
interface ResolverForModuleComputationTracker {
|
||||
|
||||
fun onResolverComputed(moduleInfo: ModuleInfo)
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): ResolverForModuleComputationTracker? = ServiceManager.getService(project, ResolverForModuleComputationTracker::class.java) ?: null
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.cfg.pseudocodeTraverser.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.referencedProperty
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -53,9 +52,12 @@ import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getDispatchReceiverWi
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.hasThisOrNoDispatchReceiver
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils.*
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.kotlin.types.isFlexible
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.util.*
|
||||
@@ -398,18 +400,6 @@ class ControlFlowInformationProvider private constructor(
|
||||
varWithValReassignErrorGenerated: MutableCollection<VariableDescriptor>
|
||||
): Boolean {
|
||||
val variableDescriptor = ctxt.variableDescriptor
|
||||
val propertyDescriptor = variableDescriptor?.referencedProperty
|
||||
if (KtPsiUtil.isBackingFieldReference(variableDescriptor) && propertyDescriptor != null) {
|
||||
val accessor = getParentOfType(expression, KtPropertyAccessor::class.java)
|
||||
if (accessor != null) {
|
||||
val accessorDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, accessor)
|
||||
if (propertyDescriptor.getter === accessorDescriptor) {
|
||||
//val can be reassigned through backing field inside its own getter
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val mayBeInitializedNotHere = ctxt.enterInitState?.mayBeInitialized() ?: false
|
||||
val hasBackingField = (variableDescriptor as? PropertyDescriptor)?.let {
|
||||
trace.get(BindingContext.BACKING_FIELD_REQUIRED, it)
|
||||
@@ -467,7 +457,12 @@ class ControlFlowInformationProvider private constructor(
|
||||
}
|
||||
}
|
||||
else {
|
||||
report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor), ctxt)
|
||||
if (KtPsiUtil.isBackingFieldReference(variableDescriptor)) {
|
||||
report(Errors.VAL_REASSIGNMENT_VIA_BACKING_FIELD.on(expression, variableDescriptor), ctxt)
|
||||
}
|
||||
else {
|
||||
report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor), ctxt)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isThisOrNoDispatchReceiver) {
|
||||
@@ -642,7 +637,7 @@ class ControlFlowInformationProvider private constructor(
|
||||
val containingClass = owner.getContainingClassOrObject()
|
||||
val containingClassDescriptor = trace.get(DECLARATION_TO_DESCRIPTOR, containingClass) as? ClassDescriptor
|
||||
if (!DescriptorUtils.isAnnotationClass(containingClassDescriptor) && containingClassDescriptor?.isHeader == false &&
|
||||
!DescriptorUtils.isEffectivelyExternal(containingClassDescriptor)
|
||||
!containingClassDescriptor.isEffectivelyExternal()
|
||||
) {
|
||||
report(UNUSED_PARAMETER.on(element, variableDescriptor), ctxt)
|
||||
}
|
||||
@@ -662,7 +657,7 @@ class ControlFlowInformationProvider private constructor(
|
||||
|| functionDescriptor.isOverridableOrOverrides
|
||||
|| owner.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|
||||
|| functionDescriptor.isHeader || functionDescriptor.isImpl
|
||||
|| DescriptorUtils.isEffectivelyExternal(functionDescriptor)
|
||||
|| functionDescriptor.isEffectivelyExternal()
|
||||
|| OperatorNameConventions.GET_VALUE == functionName
|
||||
|| OperatorNameConventions.SET_VALUE == functionName
|
||||
|| OperatorNameConventions.PROVIDE_DELEGATE == functionName) {
|
||||
@@ -777,25 +772,41 @@ class ControlFlowInformationProvider private constructor(
|
||||
for (element in instruction.owner.getValueElements(value)) {
|
||||
if (element !is KtWhenExpression) continue
|
||||
|
||||
if (element.isUsedAsExpression(trace.bindingContext)) {
|
||||
val usedAsExpression = element.isUsedAsExpression(trace.bindingContext)
|
||||
if (usedAsExpression) {
|
||||
checkImplicitCastOnConditionalExpression(element)
|
||||
}
|
||||
|
||||
if (element.elseExpression != null) continue
|
||||
|
||||
val context = trace.bindingContext
|
||||
val necessaryCases = WhenChecker.getNecessaryCases(element, context)
|
||||
if (!necessaryCases.isEmpty()) {
|
||||
trace.report(NO_ELSE_IN_WHEN.on(element, necessaryCases))
|
||||
val missingCases = WhenChecker.getMissingCases(element, context)
|
||||
|
||||
val elseEntry = element.entries.find { it.isElse }
|
||||
val subjectExpression = element.subjectExpression
|
||||
if (usedAsExpression && missingCases.isNotEmpty()) {
|
||||
if (elseEntry != null) continue
|
||||
trace.report(NO_ELSE_IN_WHEN.on(element, missingCases))
|
||||
}
|
||||
else {
|
||||
val subjectExpression = element.subjectExpression
|
||||
if (subjectExpression != null) {
|
||||
val enumClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfEnum(trace.getType(subjectExpression))
|
||||
else if (subjectExpression != null) {
|
||||
val subjectType = trace.getType(subjectExpression)
|
||||
if (elseEntry != null) {
|
||||
if (missingCases.isEmpty() && subjectType != null && !subjectType.isFlexible()) {
|
||||
val subjectClass = subjectType.constructor.declarationDescriptor as? ClassDescriptor
|
||||
val pseudocodeElement = instruction.owner.correspondingElement
|
||||
val pseudocodeDescriptor = trace[DECLARATION_TO_DESCRIPTOR, pseudocodeElement]
|
||||
if (subjectClass == null ||
|
||||
KotlinBuiltIns.isBooleanOrNullableBoolean(subjectType) ||
|
||||
subjectClass.module == pseudocodeDescriptor?.module) {
|
||||
trace.report(REDUNDANT_ELSE_IN_WHEN.on(elseEntry))
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (!usedAsExpression) {
|
||||
val enumClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType)
|
||||
if (enumClassDescriptor != null) {
|
||||
val missingCases = WhenChecker.getEnumMissingCases(element, context, enumClassDescriptor)
|
||||
if (!missingCases.isEmpty()) {
|
||||
trace.report(NON_EXHAUSTIVE_WHEN.on(element, missingCases))
|
||||
val enumMissingCases = WhenChecker.getEnumMissingCases(element, context, enumClassDescriptor)
|
||||
if (!enumMissingCases.isEmpty()) {
|
||||
trace.report(NON_EXHAUSTIVE_WHEN.on(element, enumMissingCases))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,11 +262,6 @@ object WhenChecker {
|
||||
WhenOnEnumExhaustivenessChecker,
|
||||
WhenOnSealedExhaustivenessChecker)
|
||||
|
||||
@JvmStatic
|
||||
fun getNecessaryCases(expression: KtWhenExpression, context: BindingContext) =
|
||||
if (expression.isUsedAsExpression(context)) getMissingCases(expression, context)
|
||||
else listOf()
|
||||
|
||||
@JvmStatic
|
||||
fun isWhenByEnum(expression: KtWhenExpression, context: BindingContext) =
|
||||
getClassDescriptorOfTypeIfEnum(whenSubjectType(expression, context)) != null
|
||||
|
||||
@@ -761,6 +761,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtLambdaExpression> UNUSED_LAMBDA_EXPRESSION = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> VAL_REASSIGNMENT = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> VAL_REASSIGNMENT_VIA_BACKING_FIELD = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> CAPTURED_VAL_INITIALIZATION = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> CAPTURED_MEMBER_VAL_INITIALIZATION = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> SETTER_PROJECTED_OUT = DiagnosticFactory1.create(ERROR);
|
||||
@@ -843,6 +844,7 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<KtWhenCondition> EXPECTED_CONDITION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtWhenEntry> ELSE_MISPLACED_IN_WHEN = DiagnosticFactory0.create(ERROR, ELSE_ENTRY);
|
||||
DiagnosticFactory0<KtWhenEntry> REDUNDANT_ELSE_IN_WHEN = DiagnosticFactory0.create(WARNING, ELSE_ENTRY);
|
||||
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>> NO_ELSE_IN_WHEN = DiagnosticFactory1.create(ERROR, WHEN_EXPRESSION);
|
||||
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>> NON_EXHAUSTIVE_WHEN = DiagnosticFactory1.create(WARNING, WHEN_EXPRESSION);
|
||||
DiagnosticFactory0<PsiElement> COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT = DiagnosticFactory0.create(ERROR);
|
||||
@@ -932,7 +934,7 @@ public interface Errors {
|
||||
INVISIBLE_MEMBER, NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, INVISIBLE_REFERENCE, INVISIBLE_SETTER);
|
||||
ImmutableSet<? extends DiagnosticFactory<?>> UNUSED_ELEMENT_DIAGNOSTICS = ImmutableSet.of(
|
||||
UNUSED_VARIABLE, UNUSED_PARAMETER, ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE, VARIABLE_WITH_REDUNDANT_INITIALIZER,
|
||||
UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS, UNNECESSARY_LATEINIT);
|
||||
UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS, UNNECESSARY_LATEINIT, REDUNDANT_ELSE_IN_WHEN);
|
||||
ImmutableSet<? extends DiagnosticFactory<?>> TYPE_INFERENCE_ERRORS = ImmutableSet.of(
|
||||
TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS,
|
||||
TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR,
|
||||
|
||||
@@ -299,6 +299,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(UNUSED_LAMBDA_EXPRESSION, "The lambda expression is unused. If you mean a block, you can use 'run { ... }'");
|
||||
|
||||
MAP.put(VAL_REASSIGNMENT, "Val cannot be reassigned", NAME);
|
||||
MAP.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD, "Val cannot be reassigned via backing field", NAME);
|
||||
MAP.put(CAPTURED_VAL_INITIALIZATION, "Captured values initialization is forbidden due to possible reassignment", NAME);
|
||||
MAP.put(CAPTURED_MEMBER_VAL_INITIALIZATION, "Captured member values initialization is forbidden due to possible reassignment", NAME);
|
||||
MAP.put(SETTER_PROJECTED_OUT, "Setter for ''{0}'' is removed by type projection", NAME);
|
||||
@@ -512,6 +513,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(NULL_FOR_NONNULL_TYPE, "Null can not be a value of a non-null type {0}", RENDER_TYPE);
|
||||
|
||||
MAP.put(ELSE_MISPLACED_IN_WHEN, "'else' entry must be the last one in a when-expression");
|
||||
MAP.put(REDUNDANT_ELSE_IN_WHEN, "'when' is exhaustive so 'else' is redundant here");
|
||||
MAP.put(COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT, "Deprecated syntax. Use '||' instead of commas in when-condition for 'when' without argument");
|
||||
MAP.put(DUPLICATE_LABEL_IN_WHEN, "Duplicate label in when");
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
%eof}
|
||||
|
||||
%xstate STRING RAW_STRING SHORT_TEMPLATE_ENTRY BLOCK_COMMENT DOC_COMMENT
|
||||
%state LONG_TEMPLATE_ENTRY
|
||||
%state LONG_TEMPLATE_ENTRY UNMATCHED_BACKTICK
|
||||
|
||||
DIGIT=[0-9]
|
||||
DIGIT_OR_UNDERSCORE = [_0-9]
|
||||
@@ -119,6 +119,7 @@ REGULAR_STRING_PART=[^\\\"\n\$]+
|
||||
SHORT_TEMPLATE_ENTRY=\${IDENTIFIER}
|
||||
LONELY_DOLLAR=\$
|
||||
LONG_TEMPLATE_ENTRY_START=\$\{
|
||||
LONELY_BACKTICK=`
|
||||
|
||||
%%
|
||||
|
||||
@@ -318,6 +319,8 @@ LONG_TEMPLATE_ENTRY_START=\$\{
|
||||
"#" { return KtTokens.HASH ; }
|
||||
"@" { return KtTokens.AT ; }
|
||||
|
||||
{LONELY_BACKTICK} { pushState(UNMATCHED_BACKTICK); return TokenType.BAD_CHARACTER; }
|
||||
|
||||
// error fallback
|
||||
. { return TokenType.BAD_CHARACTER; }
|
||||
// error fallback for exclusive states
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.intellij.util.containers.Stack;
|
||||
/**
|
||||
* This class is a scanner generated by
|
||||
* <a href="http://www.jflex.de/">JFlex</a> 1.7.0-SNAPSHOT
|
||||
* from the specification file <tt>/Users/endermz/projects/kotlin/compiler/frontend/src/org/jetbrains/kotlin/lexer/Kotlin.flex</tt>
|
||||
* from the specification file <tt>/Users/yole/jetbrains/kotlin/compiler/frontend/src/org/jetbrains/kotlin/lexer/Kotlin.flex</tt>
|
||||
*/
|
||||
class _JetLexer implements FlexLexer {
|
||||
|
||||
@@ -45,6 +45,7 @@ class _JetLexer implements FlexLexer {
|
||||
public static final int BLOCK_COMMENT = 8;
|
||||
public static final int DOC_COMMENT = 10;
|
||||
public static final int LONG_TEMPLATE_ENTRY = 12;
|
||||
public static final int UNMATCHED_BACKTICK = 14;
|
||||
|
||||
/**
|
||||
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
|
||||
@@ -53,7 +54,7 @@ class _JetLexer implements FlexLexer {
|
||||
* l is of the form l = 2*k, k a non negative integer
|
||||
*/
|
||||
private static final int ZZ_LEXSTATE[] = {
|
||||
0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5
|
||||
0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 0, 0
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -183,26 +184,26 @@ class _JetLexer implements FlexLexer {
|
||||
private static final int [] ZZ_ACTION = zzUnpackAction();
|
||||
|
||||
private static final String ZZ_ACTION_PACKED_0 =
|
||||
"\6\0\1\1\1\2\1\3\1\4\2\1\1\5\1\6"+
|
||||
"\1\7\1\2\1\10\1\11\1\12\1\13\1\14\3\3"+
|
||||
"\1\15\1\16\14\3\1\17\1\20\1\21\1\22\1\23"+
|
||||
"\2\1\1\24\1\25\1\26\1\27\1\30\1\31\1\32"+
|
||||
"\1\33\1\34\1\35\1\36\1\35\1\1\1\37\2\35"+
|
||||
"\1\40\1\1\1\40\3\41\1\42\1\43\1\2\1\0"+
|
||||
"\2\44\1\0\1\45\1\0\1\46\1\47\1\50\1\51"+
|
||||
"\1\0\1\52\1\0\2\2\1\44\1\53\1\54\1\55"+
|
||||
"\1\56\2\12\1\0\3\3\1\57\1\60\1\61\1\3"+
|
||||
"\1\62\2\3\1\63\13\3\1\64\1\65\1\66\1\67"+
|
||||
"\6\0\1\1\1\2\1\3\1\4\1\5\1\1\1\6"+
|
||||
"\1\7\1\10\1\2\1\11\1\12\1\13\1\14\1\15"+
|
||||
"\3\3\1\16\1\17\14\3\1\20\1\21\1\22\1\23"+
|
||||
"\1\24\2\1\1\25\1\26\1\27\1\30\1\31\1\32"+
|
||||
"\1\33\1\34\1\35\1\36\1\37\1\36\1\1\1\40"+
|
||||
"\2\36\1\41\1\1\1\41\3\42\1\43\1\44\1\2"+
|
||||
"\1\0\2\45\1\0\1\46\1\0\1\47\1\50\1\51"+
|
||||
"\1\52\1\0\1\53\1\0\2\2\1\45\1\54\1\55"+
|
||||
"\1\56\1\57\2\13\1\0\3\3\1\60\1\61\1\62"+
|
||||
"\1\3\1\63\2\3\1\64\13\3\1\65\1\66\1\67"+
|
||||
"\1\70\1\71\1\72\1\73\1\74\1\75\1\76\1\77"+
|
||||
"\1\100\1\0\1\101\2\102\2\0\1\40\1\103\1\104"+
|
||||
"\1\0\1\105\1\44\1\3\1\0\1\106\1\107\1\110"+
|
||||
"\1\111\1\0\1\112\1\113\4\3\1\114\4\3\1\115"+
|
||||
"\2\3\1\116\1\3\1\117\6\3\1\120\1\121\1\122"+
|
||||
"\2\0\1\123\2\40\1\45\1\124\1\125\1\126\2\3"+
|
||||
"\1\127\3\3\1\130\1\131\7\3\1\132\1\100\1\0"+
|
||||
"\1\133\1\134\3\3\1\135\2\3\1\136\1\137\2\3"+
|
||||
"\1\140\1\141\1\0\1\3\1\142\2\3\1\143\1\3"+
|
||||
"\1\144\2\3\1\145\3\3\1\146\1\147\1\150";
|
||||
"\1\100\1\101\1\0\1\102\2\103\2\0\1\41\1\104"+
|
||||
"\1\105\1\0\1\106\1\45\1\3\1\0\1\107\1\110"+
|
||||
"\1\111\1\112\1\0\1\113\1\114\4\3\1\115\4\3"+
|
||||
"\1\116\2\3\1\117\1\3\1\120\6\3\1\121\1\122"+
|
||||
"\1\123\2\0\1\124\2\41\1\46\1\125\1\126\1\127"+
|
||||
"\2\3\1\130\3\3\1\131\1\132\7\3\1\133\1\101"+
|
||||
"\1\0\1\134\1\135\3\3\1\136\2\3\1\137\1\140"+
|
||||
"\2\3\1\141\1\142\1\0\1\3\1\143\2\3\1\144"+
|
||||
"\1\3\1\145\2\3\1\146\3\3\1\147\1\150\1\151";
|
||||
|
||||
private static int [] zzUnpackAction() {
|
||||
int [] result = new int[231];
|
||||
@@ -646,7 +647,7 @@ class _JetLexer implements FlexLexer {
|
||||
}
|
||||
}
|
||||
|
||||
private final Stack<State> states = new Stack<>();
|
||||
private final Stack<State> states = new Stack<State>();
|
||||
private int lBraceCount;
|
||||
|
||||
private int commentStart;
|
||||
@@ -954,140 +955,144 @@ class _JetLexer implements FlexLexer {
|
||||
case 1:
|
||||
{ return TokenType.BAD_CHARACTER;
|
||||
}
|
||||
case 105: break;
|
||||
case 106: break;
|
||||
case 2:
|
||||
{ return KtTokens.INTEGER_LITERAL;
|
||||
}
|
||||
case 106: break;
|
||||
case 107: break;
|
||||
case 3:
|
||||
{ return KtTokens.IDENTIFIER;
|
||||
}
|
||||
case 107: break;
|
||||
case 108: break;
|
||||
case 4:
|
||||
{ return KtTokens.WHITE_SPACE;
|
||||
}
|
||||
case 108: break;
|
||||
case 5:
|
||||
{ return KtTokens.DIV ;
|
||||
}
|
||||
case 109: break;
|
||||
case 6:
|
||||
{ return KtTokens.HASH ;
|
||||
case 5:
|
||||
{ pushState(UNMATCHED_BACKTICK); return TokenType.BAD_CHARACTER;
|
||||
}
|
||||
case 110: break;
|
||||
case 7:
|
||||
{ return KtTokens.EXCL ;
|
||||
case 6:
|
||||
{ return KtTokens.DIV ;
|
||||
}
|
||||
case 111: break;
|
||||
case 8:
|
||||
{ return KtTokens.DOT ;
|
||||
case 7:
|
||||
{ return KtTokens.HASH ;
|
||||
}
|
||||
case 112: break;
|
||||
case 9:
|
||||
{ return KtTokens.MINUS ;
|
||||
case 8:
|
||||
{ return KtTokens.EXCL ;
|
||||
}
|
||||
case 113: break;
|
||||
case 10:
|
||||
{ return KtTokens.CHARACTER_LITERAL;
|
||||
case 9:
|
||||
{ return KtTokens.DOT ;
|
||||
}
|
||||
case 114: break;
|
||||
case 11:
|
||||
{ pushState(STRING); return KtTokens.OPEN_QUOTE;
|
||||
case 10:
|
||||
{ return KtTokens.MINUS ;
|
||||
}
|
||||
case 115: break;
|
||||
case 12:
|
||||
{ return KtTokens.LBRACE ;
|
||||
case 11:
|
||||
{ return KtTokens.CHARACTER_LITERAL;
|
||||
}
|
||||
case 116: break;
|
||||
case 13:
|
||||
{ return KtTokens.RBRACE ;
|
||||
case 12:
|
||||
{ pushState(STRING); return KtTokens.OPEN_QUOTE;
|
||||
}
|
||||
case 117: break;
|
||||
case 14:
|
||||
{ return KtTokens.MUL ;
|
||||
case 13:
|
||||
{ return KtTokens.LBRACE ;
|
||||
}
|
||||
case 118: break;
|
||||
case 15:
|
||||
{ return KtTokens.EQ ;
|
||||
case 14:
|
||||
{ return KtTokens.RBRACE ;
|
||||
}
|
||||
case 119: break;
|
||||
case 16:
|
||||
{ return KtTokens.QUEST ;
|
||||
case 15:
|
||||
{ return KtTokens.MUL ;
|
||||
}
|
||||
case 120: break;
|
||||
case 17:
|
||||
{ return KtTokens.PLUS ;
|
||||
case 16:
|
||||
{ return KtTokens.EQ ;
|
||||
}
|
||||
case 121: break;
|
||||
case 18:
|
||||
{ return KtTokens.LT ;
|
||||
case 17:
|
||||
{ return KtTokens.QUEST ;
|
||||
}
|
||||
case 122: break;
|
||||
case 19:
|
||||
{ return KtTokens.GT ;
|
||||
case 18:
|
||||
{ return KtTokens.PLUS ;
|
||||
}
|
||||
case 123: break;
|
||||
case 20:
|
||||
{ return KtTokens.PERC ;
|
||||
case 19:
|
||||
{ return KtTokens.LT ;
|
||||
}
|
||||
case 124: break;
|
||||
case 21:
|
||||
{ return KtTokens.COLON ;
|
||||
case 20:
|
||||
{ return KtTokens.GT ;
|
||||
}
|
||||
case 125: break;
|
||||
case 22:
|
||||
{ return KtTokens.LBRACKET ;
|
||||
case 21:
|
||||
{ return KtTokens.PERC ;
|
||||
}
|
||||
case 126: break;
|
||||
case 23:
|
||||
{ return KtTokens.RBRACKET ;
|
||||
case 22:
|
||||
{ return KtTokens.COLON ;
|
||||
}
|
||||
case 127: break;
|
||||
case 24:
|
||||
{ return KtTokens.LPAR ;
|
||||
case 23:
|
||||
{ return KtTokens.LBRACKET ;
|
||||
}
|
||||
case 128: break;
|
||||
case 25:
|
||||
{ return KtTokens.RPAR ;
|
||||
case 24:
|
||||
{ return KtTokens.RBRACKET ;
|
||||
}
|
||||
case 129: break;
|
||||
case 26:
|
||||
{ return KtTokens.SEMICOLON ;
|
||||
case 25:
|
||||
{ return KtTokens.LPAR ;
|
||||
}
|
||||
case 130: break;
|
||||
case 27:
|
||||
{ return KtTokens.COMMA ;
|
||||
case 26:
|
||||
{ return KtTokens.RPAR ;
|
||||
}
|
||||
case 131: break;
|
||||
case 28:
|
||||
{ return KtTokens.AT ;
|
||||
case 27:
|
||||
{ return KtTokens.SEMICOLON ;
|
||||
}
|
||||
case 132: break;
|
||||
case 29:
|
||||
{ return KtTokens.REGULAR_STRING_PART;
|
||||
case 28:
|
||||
{ return KtTokens.COMMA ;
|
||||
}
|
||||
case 133: break;
|
||||
case 30:
|
||||
{ popState(); yypushback(1); return KtTokens.DANGLING_NEWLINE;
|
||||
case 29:
|
||||
{ return KtTokens.AT ;
|
||||
}
|
||||
case 134: break;
|
||||
case 31:
|
||||
{ popState(); return KtTokens.CLOSING_QUOTE;
|
||||
case 30:
|
||||
{ return KtTokens.REGULAR_STRING_PART;
|
||||
}
|
||||
case 135: break;
|
||||
case 32:
|
||||
{ popState(); return KtTokens.IDENTIFIER;
|
||||
case 31:
|
||||
{ popState(); yypushback(1); return KtTokens.DANGLING_NEWLINE;
|
||||
}
|
||||
case 136: break;
|
||||
case 33:
|
||||
{
|
||||
case 32:
|
||||
{ popState(); return KtTokens.CLOSING_QUOTE;
|
||||
}
|
||||
case 137: break;
|
||||
case 34:
|
||||
{ lBraceCount++; return KtTokens.LBRACE;
|
||||
case 33:
|
||||
{ popState(); return KtTokens.IDENTIFIER;
|
||||
}
|
||||
case 138: break;
|
||||
case 34:
|
||||
{
|
||||
}
|
||||
case 139: break;
|
||||
case 35:
|
||||
{ lBraceCount++; return KtTokens.LBRACE;
|
||||
}
|
||||
case 140: break;
|
||||
case 36:
|
||||
{ if (lBraceCount == 0) {
|
||||
popState();
|
||||
return KtTokens.LONG_TEMPLATE_ENTRY_END;
|
||||
@@ -1095,30 +1100,30 @@ class _JetLexer implements FlexLexer {
|
||||
lBraceCount--;
|
||||
return KtTokens.RBRACE;
|
||||
}
|
||||
case 139: break;
|
||||
case 36:
|
||||
case 141: break;
|
||||
case 37:
|
||||
{ return KtTokens.FLOAT_LITERAL;
|
||||
}
|
||||
case 140: break;
|
||||
case 37:
|
||||
case 142: break;
|
||||
case 38:
|
||||
{ return KtTokens.FIELD_IDENTIFIER;
|
||||
}
|
||||
case 141: break;
|
||||
case 38:
|
||||
case 143: break;
|
||||
case 39:
|
||||
{ return KtTokens.EOL_COMMENT;
|
||||
}
|
||||
case 142: break;
|
||||
case 39:
|
||||
case 144: break;
|
||||
case 40:
|
||||
{ pushState(BLOCK_COMMENT);
|
||||
commentDepth = 0;
|
||||
commentStart = getTokenStart();
|
||||
}
|
||||
case 143: break;
|
||||
case 40:
|
||||
case 145: break;
|
||||
case 41:
|
||||
{ return KtTokens.DIVEQ ;
|
||||
}
|
||||
case 144: break;
|
||||
case 41:
|
||||
case 146: break;
|
||||
case 42:
|
||||
{ if (zzCurrentPos == 0) {
|
||||
return KtTokens.SHEBANG_COMMENT;
|
||||
}
|
||||
@@ -1127,114 +1132,114 @@ class _JetLexer implements FlexLexer {
|
||||
return KtTokens.HASH;
|
||||
}
|
||||
}
|
||||
case 145: break;
|
||||
case 42:
|
||||
case 147: break;
|
||||
case 43:
|
||||
{ return KtTokens.EXCLEQ ;
|
||||
}
|
||||
case 146: break;
|
||||
case 43:
|
||||
case 148: break;
|
||||
case 44:
|
||||
{ return KtTokens.RANGE ;
|
||||
}
|
||||
case 147: break;
|
||||
case 44:
|
||||
case 149: break;
|
||||
case 45:
|
||||
{ return KtTokens.MINUSMINUS;
|
||||
}
|
||||
case 148: break;
|
||||
case 45:
|
||||
case 150: break;
|
||||
case 46:
|
||||
{ return KtTokens.MINUSEQ ;
|
||||
}
|
||||
case 149: break;
|
||||
case 46:
|
||||
case 151: break;
|
||||
case 47:
|
||||
{ return KtTokens.ARROW ;
|
||||
}
|
||||
case 150: break;
|
||||
case 47:
|
||||
case 152: break;
|
||||
case 48:
|
||||
{ return KtTokens.IS_KEYWORD ;
|
||||
}
|
||||
case 151: break;
|
||||
case 48:
|
||||
case 153: break;
|
||||
case 49:
|
||||
{ return KtTokens.IN_KEYWORD ;
|
||||
}
|
||||
case 152: break;
|
||||
case 49:
|
||||
case 154: break;
|
||||
case 50:
|
||||
{ return KtTokens.IF_KEYWORD ;
|
||||
}
|
||||
case 153: break;
|
||||
case 50:
|
||||
case 155: break;
|
||||
case 51:
|
||||
{ return KtTokens.MULTEQ ;
|
||||
}
|
||||
case 154: break;
|
||||
case 51:
|
||||
case 156: break;
|
||||
case 52:
|
||||
{ return KtTokens.AS_KEYWORD ;
|
||||
}
|
||||
case 155: break;
|
||||
case 52:
|
||||
case 157: break;
|
||||
case 53:
|
||||
{ return KtTokens.DO_KEYWORD ;
|
||||
}
|
||||
case 156: break;
|
||||
case 53:
|
||||
case 158: break;
|
||||
case 54:
|
||||
{ return KtTokens.EQEQ ;
|
||||
}
|
||||
case 157: break;
|
||||
case 54:
|
||||
case 159: break;
|
||||
case 55:
|
||||
{ return KtTokens.DOUBLE_ARROW;
|
||||
}
|
||||
case 158: break;
|
||||
case 55:
|
||||
case 160: break;
|
||||
case 56:
|
||||
{ return KtTokens.PLUSEQ ;
|
||||
}
|
||||
case 159: break;
|
||||
case 56:
|
||||
case 161: break;
|
||||
case 57:
|
||||
{ return KtTokens.PLUSPLUS ;
|
||||
}
|
||||
case 160: break;
|
||||
case 57:
|
||||
case 162: break;
|
||||
case 58:
|
||||
{ return KtTokens.LTEQ ;
|
||||
}
|
||||
case 161: break;
|
||||
case 58:
|
||||
case 163: break;
|
||||
case 59:
|
||||
{ return KtTokens.GTEQ ;
|
||||
}
|
||||
case 162: break;
|
||||
case 59:
|
||||
case 164: break;
|
||||
case 60:
|
||||
{ return KtTokens.ANDAND ;
|
||||
}
|
||||
case 163: break;
|
||||
case 60:
|
||||
case 165: break;
|
||||
case 61:
|
||||
{ return KtTokens.OROR ;
|
||||
}
|
||||
case 164: break;
|
||||
case 61:
|
||||
case 166: break;
|
||||
case 62:
|
||||
{ return KtTokens.PERCEQ ;
|
||||
}
|
||||
case 165: break;
|
||||
case 62:
|
||||
case 167: break;
|
||||
case 63:
|
||||
{ return KtTokens.COLONCOLON;
|
||||
}
|
||||
case 166: break;
|
||||
case 63:
|
||||
case 168: break;
|
||||
case 64:
|
||||
{ return KtTokens.DOUBLE_SEMICOLON;
|
||||
}
|
||||
case 167: break;
|
||||
case 64:
|
||||
case 169: break;
|
||||
case 65:
|
||||
{ pushState(SHORT_TEMPLATE_ENTRY);
|
||||
yypushback(yylength() - 1);
|
||||
return KtTokens.SHORT_TEMPLATE_ENTRY_START;
|
||||
}
|
||||
case 168: break;
|
||||
case 65:
|
||||
case 170: break;
|
||||
case 66:
|
||||
{ pushState(LONG_TEMPLATE_ENTRY); return KtTokens.LONG_TEMPLATE_ENTRY_START;
|
||||
}
|
||||
case 169: break;
|
||||
case 66:
|
||||
case 171: break;
|
||||
case 67:
|
||||
{ return KtTokens.ESCAPE_SEQUENCE;
|
||||
}
|
||||
case 170: break;
|
||||
case 67:
|
||||
case 172: break;
|
||||
case 68:
|
||||
{ commentDepth++;
|
||||
}
|
||||
case 171: break;
|
||||
case 68:
|
||||
case 173: break;
|
||||
case 69:
|
||||
{ if (commentDepth > 0) {
|
||||
commentDepth--;
|
||||
}
|
||||
@@ -1245,66 +1250,66 @@ class _JetLexer implements FlexLexer {
|
||||
return commentStateToTokenType(state);
|
||||
}
|
||||
}
|
||||
case 172: break;
|
||||
case 69:
|
||||
case 174: break;
|
||||
case 70:
|
||||
{ yypushback(2); return KtTokens.INTEGER_LITERAL;
|
||||
}
|
||||
case 173: break;
|
||||
case 70:
|
||||
case 175: break;
|
||||
case 71:
|
||||
{ pushState(DOC_COMMENT);
|
||||
commentDepth = 0;
|
||||
commentStart = getTokenStart();
|
||||
}
|
||||
case 174: break;
|
||||
case 71:
|
||||
case 176: break;
|
||||
case 72:
|
||||
{ return KtTokens.NOT_IS;
|
||||
}
|
||||
case 175: break;
|
||||
case 72:
|
||||
case 177: break;
|
||||
case 73:
|
||||
{ return KtTokens.NOT_IN;
|
||||
}
|
||||
case 176: break;
|
||||
case 73:
|
||||
case 178: break;
|
||||
case 74:
|
||||
{ return KtTokens.EXCLEQEQEQ;
|
||||
}
|
||||
case 177: break;
|
||||
case 74:
|
||||
case 179: break;
|
||||
case 75:
|
||||
{ return KtTokens.RESERVED ;
|
||||
}
|
||||
case 178: break;
|
||||
case 75:
|
||||
case 180: break;
|
||||
case 76:
|
||||
{ pushState(RAW_STRING); return KtTokens.OPEN_QUOTE;
|
||||
}
|
||||
case 179: break;
|
||||
case 76:
|
||||
case 181: break;
|
||||
case 77:
|
||||
{ return KtTokens.TRY_KEYWORD ;
|
||||
}
|
||||
case 180: break;
|
||||
case 77:
|
||||
case 182: break;
|
||||
case 78:
|
||||
{ return KtTokens.AS_SAFE;
|
||||
}
|
||||
case 181: break;
|
||||
case 78:
|
||||
case 183: break;
|
||||
case 79:
|
||||
{ return KtTokens.FUN_KEYWORD ;
|
||||
}
|
||||
case 182: break;
|
||||
case 79:
|
||||
case 184: break;
|
||||
case 80:
|
||||
{ return KtTokens.FOR_KEYWORD ;
|
||||
}
|
||||
case 183: break;
|
||||
case 80:
|
||||
case 185: break;
|
||||
case 81:
|
||||
{ return KtTokens.VAL_KEYWORD ;
|
||||
}
|
||||
case 184: break;
|
||||
case 81:
|
||||
case 186: break;
|
||||
case 82:
|
||||
{ return KtTokens.VAR_KEYWORD ;
|
||||
}
|
||||
case 185: break;
|
||||
case 82:
|
||||
case 187: break;
|
||||
case 83:
|
||||
{ return KtTokens.EQEQEQ ;
|
||||
}
|
||||
case 186: break;
|
||||
case 83:
|
||||
case 188: break;
|
||||
case 84:
|
||||
{ int length = yytext().length();
|
||||
if (length <= 3) { // closing """
|
||||
popState();
|
||||
@@ -1315,91 +1320,91 @@ class _JetLexer implements FlexLexer {
|
||||
return KtTokens.REGULAR_STRING_PART;
|
||||
}
|
||||
}
|
||||
case 187: break;
|
||||
case 84:
|
||||
case 189: break;
|
||||
case 85:
|
||||
{ return KtTokens.BLOCK_COMMENT;
|
||||
}
|
||||
case 188: break;
|
||||
case 85:
|
||||
case 190: break;
|
||||
case 86:
|
||||
{ yypushback(3); return KtTokens.EXCL;
|
||||
}
|
||||
case 189: break;
|
||||
case 86:
|
||||
case 191: break;
|
||||
case 87:
|
||||
{ return KtTokens.THIS_KEYWORD ;
|
||||
}
|
||||
case 190: break;
|
||||
case 87:
|
||||
case 192: break;
|
||||
case 88:
|
||||
{ return KtTokens.TRUE_KEYWORD ;
|
||||
}
|
||||
case 191: break;
|
||||
case 88:
|
||||
case 193: break;
|
||||
case 89:
|
||||
{ return KtTokens.ELSE_KEYWORD ;
|
||||
}
|
||||
case 192: break;
|
||||
case 89:
|
||||
case 194: break;
|
||||
case 90:
|
||||
{ return KtTokens.NULL_KEYWORD ;
|
||||
}
|
||||
case 193: break;
|
||||
case 90:
|
||||
case 195: break;
|
||||
case 91:
|
||||
{ return KtTokens.WHEN_KEYWORD ;
|
||||
}
|
||||
case 194: break;
|
||||
case 91:
|
||||
case 196: break;
|
||||
case 92:
|
||||
{ popState(); return KtTokens.THIS_KEYWORD;
|
||||
}
|
||||
case 195: break;
|
||||
case 92:
|
||||
case 197: break;
|
||||
case 93:
|
||||
{ return KtTokens.THROW_KEYWORD ;
|
||||
}
|
||||
case 196: break;
|
||||
case 93:
|
||||
case 198: break;
|
||||
case 94:
|
||||
{ return KtTokens.SUPER_KEYWORD ;
|
||||
}
|
||||
case 197: break;
|
||||
case 94:
|
||||
case 199: break;
|
||||
case 95:
|
||||
{ return KtTokens.FALSE_KEYWORD ;
|
||||
}
|
||||
case 198: break;
|
||||
case 95:
|
||||
case 200: break;
|
||||
case 96:
|
||||
{ return KtTokens.CLASS_KEYWORD ;
|
||||
}
|
||||
case 199: break;
|
||||
case 96:
|
||||
case 201: break;
|
||||
case 97:
|
||||
{ return KtTokens.BREAK_KEYWORD ;
|
||||
}
|
||||
case 200: break;
|
||||
case 97:
|
||||
case 202: break;
|
||||
case 98:
|
||||
{ return KtTokens.WHILE_KEYWORD ;
|
||||
}
|
||||
case 201: break;
|
||||
case 98:
|
||||
case 203: break;
|
||||
case 99:
|
||||
{ return KtTokens.TYPEOF_KEYWORD ;
|
||||
}
|
||||
case 202: break;
|
||||
case 99:
|
||||
case 204: break;
|
||||
case 100:
|
||||
{ return KtTokens.RETURN_KEYWORD ;
|
||||
}
|
||||
case 203: break;
|
||||
case 100:
|
||||
case 205: break;
|
||||
case 101:
|
||||
{ return KtTokens.OBJECT_KEYWORD ;
|
||||
}
|
||||
case 204: break;
|
||||
case 101:
|
||||
case 206: break;
|
||||
case 102:
|
||||
{ return KtTokens.PACKAGE_KEYWORD ;
|
||||
}
|
||||
case 205: break;
|
||||
case 102:
|
||||
case 207: break;
|
||||
case 103:
|
||||
{ return KtTokens.CONTINUE_KEYWORD ;
|
||||
}
|
||||
case 206: break;
|
||||
case 103:
|
||||
case 208: break;
|
||||
case 104:
|
||||
{ return KtTokens.TYPE_ALIAS_KEYWORD ;
|
||||
}
|
||||
case 207: break;
|
||||
case 104:
|
||||
case 209: break;
|
||||
case 105:
|
||||
{ return KtTokens.INTERFACE_KEYWORD ;
|
||||
}
|
||||
case 208: break;
|
||||
case 210: break;
|
||||
default:
|
||||
zzScanError(ZZ_NO_MATCH);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -136,6 +136,7 @@ private val MODIFIERS_TO_REPLACE = mapOf(
|
||||
private val MODIFIERS_ORDER = listOf(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD,
|
||||
FINAL_KEYWORD, OPEN_KEYWORD, ABSTRACT_KEYWORD,
|
||||
OVERRIDE_KEYWORD,
|
||||
LATEINIT_KEYWORD,
|
||||
SUSPEND_KEYWORD,
|
||||
INNER_KEYWORD,
|
||||
ENUM_KEYWORD, COMPANION_KEYWORD, INFIX_KEYWORD, OPERATOR_KEYWORD, DATA_KEYWORD)
|
||||
|
||||
@@ -23,12 +23,12 @@ object KotlinStubVersions {
|
||||
// Though only kotlin declarations (no code in the bodies) are stubbed, please do increase this version
|
||||
// if you are not 100% sure it can be avoided.
|
||||
// Increasing this version will lead to reindexing of all kotlin source files on the first IDE startup with the new version.
|
||||
const val SOURCE_STUB_VERSION = 121
|
||||
const val SOURCE_STUB_VERSION = 123
|
||||
|
||||
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
|
||||
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
|
||||
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
|
||||
private const val BINARY_STUB_VERSION = 58
|
||||
private const val BINARY_STUB_VERSION = 60
|
||||
|
||||
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
|
||||
// Increasing this version will lead to reindexing of all classfiles.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi.stubs.elements;
|
||||
|
||||
import com.intellij.psi.stubs.IndexSink;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.stubs.StubInputStream;
|
||||
import com.intellij.psi.stubs.StubOutputStream;
|
||||
@@ -63,4 +64,9 @@ public class KtParameterElementType extends KtStubElementType<KotlinParameterStu
|
||||
|
||||
return new KotlinParameterStubImpl(parentStub, fqName, name, isMutable, hasValOrValNode, hasDefaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void indexStub(@NotNull KotlinParameterStub stub, @NotNull IndexSink sink) {
|
||||
StubIndexService.getInstance().indexParameter(stub, sink);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,12 +87,9 @@ public abstract class KtStubElementType<StubT extends StubElement, PsiT extends
|
||||
@Override
|
||||
public boolean shouldCreateStub(ASTNode node) {
|
||||
PsiElement psi = node.getPsi();
|
||||
if (psi instanceof KtClassOrObject) {
|
||||
if (psi instanceof KtClassOrObject || psi instanceof KtFunction) {
|
||||
return true;
|
||||
}
|
||||
if (psi instanceof KtFunction) {
|
||||
return !((KtFunction) psi).isLocal();
|
||||
}
|
||||
if (psi instanceof KtProperty) {
|
||||
return !((KtProperty) psi).isLocal();
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ open class StubIndexService protected constructor() {
|
||||
open fun indexProperty(stub: KotlinPropertyStub, sink: IndexSink) {
|
||||
}
|
||||
|
||||
open fun indexParameter(stub: KotlinParameterStub, sink: IndexSink) {
|
||||
}
|
||||
|
||||
open fun indexAnnotation(stub: KotlinAnnotationEntryStub, sink: IndexSink) {
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ import java.util.*;
|
||||
import static org.jetbrains.kotlin.config.LanguageFeature.TopLevelSealedInheritance;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.isEffectivelyExternal;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
public class BodyResolver {
|
||||
@@ -165,7 +166,7 @@ public class BodyResolver {
|
||||
@NotNull KtSecondaryConstructor constructor,
|
||||
@NotNull ClassConstructorDescriptor descriptor
|
||||
) {
|
||||
if (descriptor.isHeader() || DescriptorUtils.isEffectivelyExternal(descriptor)) {
|
||||
if (descriptor.isHeader() || isEffectivelyExternal(descriptor)) {
|
||||
// For header and external classes, we do not resolve constructor delegation calls because they are prohibited
|
||||
return DataFlowInfo.Companion.getEMPTY();
|
||||
}
|
||||
@@ -366,7 +367,7 @@ public class BodyResolver {
|
||||
descriptor.getUnsubstitutedPrimaryConstructor() != null &&
|
||||
superClass.getKind() != ClassKind.INTERFACE &&
|
||||
!superClass.getConstructors().isEmpty() &&
|
||||
!descriptor.isHeader() && !DescriptorUtils.isEffectivelyExternal(descriptor) &&
|
||||
!descriptor.isHeader() && !isEffectivelyExternal(descriptor) &&
|
||||
!ErrorUtils.isError(superClass)
|
||||
) {
|
||||
trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembers
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
@@ -697,7 +698,7 @@ class DeclarationsChecker(
|
||||
}
|
||||
else {
|
||||
val isUninitialized = trace.bindingContext.get(BindingContext.IS_UNINITIALIZED, propertyDescriptor) ?: false
|
||||
val isExternal = DescriptorUtils.isEffectivelyExternal(propertyDescriptor)
|
||||
val isExternal = propertyDescriptor.isEffectivelyExternal()
|
||||
if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit && !isHeader && isUninitialized && !isExternal) {
|
||||
if (containingDeclaration !is ClassDescriptor || hasAccessorImplementation) {
|
||||
trace.report(MUST_BE_INITIALIZED.on(property))
|
||||
@@ -737,7 +738,7 @@ class DeclarationsChecker(
|
||||
|
||||
val containingDescriptor = functionDescriptor.containingDeclaration
|
||||
val hasAbstractModifier = function.hasModifier(KtTokens.ABSTRACT_KEYWORD)
|
||||
val hasExternalModifier = DescriptorUtils.isEffectivelyExternal(functionDescriptor)
|
||||
val hasExternalModifier = functionDescriptor.isEffectivelyExternal()
|
||||
|
||||
if (containingDescriptor is ClassDescriptor) {
|
||||
val inInterface = containingDescriptor.kind == ClassKind.INTERFACE
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.checkers
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtThisExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.createDeprecationDiagnostic
|
||||
import org.jetbrains.kotlin.resolve.getDeprecations
|
||||
@@ -30,6 +31,7 @@ class DeprecatedClassifierUsageChecker : ClassifierUsageChecker {
|
||||
element: PsiElement,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
if (element.parent is KtThisExpression) return
|
||||
for (deprecation in targetDescriptor.getDeprecations(languageVersionSettings)) {
|
||||
trace.report(createDeprecationDiagnostic(element, deprecation, languageVersionSettings))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.LocalVariableResolver
|
||||
import org.jetbrains.kotlin.resolve.TypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
@@ -84,8 +85,9 @@ class DestructuringDeclarationResolver(
|
||||
if (receiver == null) return errorType()
|
||||
|
||||
val expectedType = getExpectedTypeForComponent(context, entry)
|
||||
val newContext = context.replaceExpectedType(expectedType).replaceContextDependency(ContextDependency.INDEPENDENT)
|
||||
val results = fakeCallResolver.resolveFakeCall(
|
||||
context.replaceExpectedType(expectedType), receiver, componentName,
|
||||
newContext, receiver, componentName,
|
||||
entry, initializer ?: entry, FakeCallKind.COMPONENT, emptyList()
|
||||
)
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.build.GeneratedFile
|
||||
import org.jetbrains.kotlin.incremental.snapshots.FileSnapshotMap
|
||||
import org.jetbrains.kotlin.incremental.storage.BasicStringMap
|
||||
import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
|
||||
@@ -31,26 +32,36 @@ class GradleIncrementalCacheImpl(
|
||||
private val reporter: ICReporter
|
||||
) : IncrementalCacheImpl<TargetId>(targetDataRoot, targetOutputDir, target) {
|
||||
companion object {
|
||||
private val SOURCES_TO_CLASSFILES = "sources-to-classfiles"
|
||||
private val GENERATED_SOURCE_SNAPSHOTS = "generated-source-snapshot"
|
||||
private val SOURCE_TO_OUTPUT_FILES = "source-to-output"
|
||||
private val SOURCE_SNAPSHOTS = "source-snapshot"
|
||||
}
|
||||
|
||||
internal val sourceToClassfilesMap = registerMap(SourceToClassfilesMap(SOURCES_TO_CLASSFILES.storageFile))
|
||||
internal val generatedSourceSnapshotMap = registerMap(FileSnapshotMap(GENERATED_SOURCE_SNAPSHOTS.storageFile))
|
||||
internal val sourceToOutputMap = registerMap(SourceToOutputFilesMap(SOURCE_TO_OUTPUT_FILES.storageFile))
|
||||
internal val sourceSnapshotMap = registerMap(FileSnapshotMap(SOURCE_SNAPSHOTS.storageFile))
|
||||
|
||||
fun removeClassfilesBySources(sources: Iterable<File>): Unit =
|
||||
sources.forEach { sourceToClassfilesMap.remove(it) }
|
||||
// generatedFiles can contain multiple entries with the same source file
|
||||
// for example Kapt3 IC will generate a .java stub and .class stub for each source file
|
||||
fun registerOutputForSourceFiles(generatedFiles: List<GeneratedFile<*>>) {
|
||||
val sourceToOutput = MultiMap<File, File>()
|
||||
|
||||
override fun saveFileToCache(generatedClass: GeneratedJvmClass<TargetId>): CompilationResult {
|
||||
generatedClass.sourceFiles.forEach { sourceToClassfilesMap.add(it, generatedClass.outputFile) }
|
||||
return super.saveFileToCache(generatedClass)
|
||||
for (generatedFile in generatedFiles) {
|
||||
for (source in generatedFile.sourceFiles) {
|
||||
sourceToOutput.putValue(source, generatedFile.outputFile)
|
||||
}
|
||||
}
|
||||
|
||||
for ((source, outputs) in sourceToOutput.entrySet()) {
|
||||
sourceToOutputMap[source] = outputs
|
||||
}
|
||||
}
|
||||
|
||||
inner class SourceToClassfilesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
fun add(sourceFile: File, classFile: File) {
|
||||
storage.append(sourceFile.absolutePath, classFile.absolutePath)
|
||||
fun removeOutputForSourceFiles(sources: Iterable<File>) {
|
||||
sources.forEach { sourceToOutputMap.remove(it) }
|
||||
}
|
||||
|
||||
inner class SourceToOutputFilesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
|
||||
storage[sourceFile.absolutePath] = outputFiles.map { it.absolutePath }
|
||||
}
|
||||
|
||||
operator fun get(sourceFile: File): Collection<File> =
|
||||
|
||||
@@ -267,7 +267,7 @@ class IncrementalJvmCompilerRunner(
|
||||
when (compilationMode) {
|
||||
is CompilationMode.Incremental -> {
|
||||
dirtySources = ArrayList(compilationMode.dirtyFiles)
|
||||
args.classpathAsList += args.destinationAsFile
|
||||
args.classpathAsList += args.destinationAsFile.apply { mkdirs() }
|
||||
}
|
||||
is CompilationMode.Rebuild -> {
|
||||
dirtySources = allKotlinSources.toMutableList()
|
||||
@@ -288,7 +288,7 @@ class IncrementalJvmCompilerRunner(
|
||||
val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING)
|
||||
val outdatedClasses = caches.incrementalCache.classesBySources(dirtySources)
|
||||
caches.incrementalCache.markOutputClassesDirty(dirtySources)
|
||||
caches.incrementalCache.removeClassfilesBySources(dirtySources)
|
||||
caches.incrementalCache.removeOutputForSourceFiles(dirtySources)
|
||||
|
||||
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
|
||||
|
||||
@@ -300,8 +300,8 @@ class IncrementalJvmCompilerRunner(
|
||||
|
||||
val compilerOutput = compileChanged(listOf(targetId), sourcesToCompile.toSet(), args, { caches.incrementalCache }, lookupTracker, messageCollector)
|
||||
exitCode = compilerOutput.exitCode
|
||||
val generatedClassFiles = compilerOutput.generatedFiles
|
||||
anyClassesCompiled = anyClassesCompiled || generatedClassFiles.isNotEmpty() || removedKotlinSources.isNotEmpty()
|
||||
val generatedFiles = compilerOutput.generatedFiles
|
||||
anyClassesCompiled = anyClassesCompiled || generatedFiles.isNotEmpty() || removedKotlinSources.isNotEmpty()
|
||||
|
||||
if (exitCode == ExitCode.OK) {
|
||||
dirtySourcesSinceLastTimeFile.delete()
|
||||
@@ -313,15 +313,16 @@ class IncrementalJvmCompilerRunner(
|
||||
|
||||
if (compilationMode is CompilationMode.Incremental) {
|
||||
val dirtySourcesSet = dirtySources.toHashSet()
|
||||
val additionalDirtyFiles = additionalDirtyFiles(caches, generatedClassFiles).filter { it !in dirtySourcesSet }
|
||||
val additionalDirtyFiles = additionalDirtyFiles(caches, generatedFiles).filter { it !in dirtySourcesSet }
|
||||
if (additionalDirtyFiles.isNotEmpty()) {
|
||||
dirtySources.addAll(additionalDirtyFiles)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
allGeneratedFiles.addAll(generatedClassFiles)
|
||||
val compilationResult = updateIncrementalCaches(listOf(targetId), generatedClassFiles,
|
||||
allGeneratedFiles.addAll(generatedFiles)
|
||||
caches.incrementalCache.registerOutputForSourceFiles(generatedFiles)
|
||||
val compilationResult = updateIncrementalCaches(listOf(targetId), generatedFiles,
|
||||
compiledWithErrors = exitCode != ExitCode.OK,
|
||||
getIncrementalCache = { caches.incrementalCache })
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.incremental
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import java.io.File
|
||||
|
||||
internal const val STANDALONE_CACHE_VERSION = 0
|
||||
internal const val STANDALONE_CACHE_VERSION = 1
|
||||
internal const val STANDALONE_VERSION_FILE_NAME = "standalone-ic-format-version.txt"
|
||||
|
||||
fun standaloneCacheVersion(dataRoot: File): CacheVersion =
|
||||
|
||||
@@ -69,7 +69,7 @@ abstract class LightClassGenerationSupport {
|
||||
|
||||
abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
|
||||
abstract fun getMultifilePartClasses(partFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
abstract fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
|
||||
abstract fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
|
||||
|
||||
@@ -247,3 +247,11 @@ object LightClassUtil {
|
||||
override fun iterator(): Iterator<PsiMethod> = allMethods.iterator()
|
||||
}
|
||||
}
|
||||
|
||||
fun KtNamedDeclaration.getAccessorLightMethods(): LightClassUtil.PropertyAccessorsPsiMethods {
|
||||
return when (this) {
|
||||
is KtProperty -> LightClassUtil.getLightClassPropertyMethods(this)
|
||||
is KtParameter -> LightClassUtil.getLightClassPropertyMethods(this)
|
||||
else -> throw IllegalStateException("Unexpected property type: ${this}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ import org.jetbrains.kotlin.asJava.builder.LightClassData
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForClassOrObject
|
||||
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightSimpleModifierList
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList
|
||||
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
@@ -180,7 +180,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
||||
|
||||
override fun getName(): String? = classOrObject.nameAsName?.asString()
|
||||
|
||||
private val _modifierList: PsiModifierList by lazyPub { KtLightSimpleModifierList(this@KtLightClassForSourceDeclaration, computeModifiers()) }
|
||||
private val _modifierList: PsiModifierList by lazyPub { KtLightClassModifierList(this) }
|
||||
|
||||
override fun getModifierList(): PsiModifierList? = _modifierList
|
||||
|
||||
@@ -390,7 +390,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
||||
val fqName = FqNameUnsafe(qualifiedName)
|
||||
val mappedQName =
|
||||
if (fqName.isSafe)
|
||||
JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(fqName.toSafe())?.asSingleFqName()?.asString()
|
||||
JavaToKotlinClassMap.mapJavaToKotlin(fqName.toSafe())?.asSingleFqName()?.asString()
|
||||
else null
|
||||
if (qualifiedName == mappedQName) return true
|
||||
|
||||
@@ -452,8 +452,28 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
||||
|
||||
override val originKind: LightClassOriginKind
|
||||
get() = LightClassOriginKind.SOURCE
|
||||
|
||||
private class KtLightClassModifierList(containingClass: KtLightClassForSourceDeclaration)
|
||||
: KtLightModifierList<KtLightClassForSourceDeclaration>(containingClass) {
|
||||
|
||||
private val modifiers by lazyPub { containingClass.computeModifiers() }
|
||||
|
||||
override fun hasModifierProperty(name: String): Boolean {
|
||||
if (name != PsiModifier.FINAL) {
|
||||
return name in modifiers
|
||||
}
|
||||
|
||||
val isFinalByPsi = PsiModifier.FINAL in modifiers
|
||||
// annotations can make class open via 'allopen' plugin
|
||||
if (!owner.isPossiblyAffectedByAllOpen() || !isFinalByPsi) return isFinalByPsi
|
||||
|
||||
return clsDelegate.hasModifierProperty(PsiModifier.FINAL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun KtLightClassForSourceDeclaration.isPossiblyAffectedByAllOpen() = !isAnnotationType && !isInterface && kotlinOrigin.annotationEntries.isNotEmpty()
|
||||
|
||||
fun getOutermostClassOrObject(classOrObject: KtClassOrObject): KtClassOrObject {
|
||||
val outermostClass = KtPsiUtil.getOutermostClassOrObject(classOrObject) ?:
|
||||
throw IllegalStateException("Attempt to build a light class for a local class: " + classOrObject.text)
|
||||
@@ -487,4 +507,4 @@ fun KtClassOrObject.defaultJavaAncestorQualifiedName(): String? {
|
||||
isInterface() -> CommonClassNames.JAVA_LANG_OBJECT // see com.intellij.psi.impl.PsiClassImplUtil.getSuperClass
|
||||
else -> CommonClassNames.JAVA_LANG_OBJECT
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,5 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.asJava.classes
|
||||
|
||||
import com.intellij.psi.impl.light.LightElement
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
|
||||
// NOTE: avoid using blocking lazy in light classes, it leads to deadlocks
|
||||
fun <T> lazyPub(initializer: () -> T) = lazy(LazyThreadSafetyMode.PUBLICATION, initializer)
|
||||
fun <T> lazyPub(initializer: () -> T) = lazy(LazyThreadSafetyMode.PUBLICATION, initializer)
|
||||
|
||||
fun LightElement.cannotModify(): Nothing {
|
||||
throw IncorrectOperationException("Modification not implemented.")
|
||||
}
|
||||
@@ -18,13 +18,12 @@ package org.jetbrains.kotlin.asJava.elements
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiVariableEx
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForEnumEntry
|
||||
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
@@ -41,8 +40,7 @@ sealed class KtLightFieldImpl<D : PsiField>(
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
get() = super.clsDelegate as D
|
||||
|
||||
@Throws(IncorrectOperationException::class)
|
||||
override fun setInitializer(initializer: PsiExpression?) = throw IncorrectOperationException("Not supported")
|
||||
override fun setInitializer(initializer: PsiExpression?) = cannotModify()
|
||||
|
||||
override fun getType() = clsDelegate.type
|
||||
|
||||
@@ -52,8 +50,7 @@ sealed class KtLightFieldImpl<D : PsiField>(
|
||||
|
||||
override fun hasInitializer() = clsDelegate.hasInitializer()
|
||||
|
||||
@Throws(IncorrectOperationException::class)
|
||||
override fun normalizeDeclaration() = throw IncorrectOperationException("Not supported")
|
||||
override fun normalizeDeclaration() = cannotModify()
|
||||
|
||||
override fun computeConstantValue() = clsDelegate.computeConstantValue()
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.asJava.builder.LightElementOrigin
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||
import org.jetbrains.kotlin.asJava.classes.isPossiblyAffectedByAllOpen
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
@@ -79,7 +81,10 @@ private class KtLightMemberModifierList(
|
||||
) : KtLightModifierList<KtLightMember<*>>(owner) {
|
||||
override fun hasModifierProperty(name: String) = when {
|
||||
name == PsiModifier.ABSTRACT && isImplementationInInterface() -> false
|
||||
// pretend this method behaves like a default method
|
||||
name == PsiModifier.DEFAULT && isImplementationInInterface() -> true
|
||||
name == PsiModifier.FINAL && ((owner.containingClass as? KtLightClassForSourceDeclaration)?.isPossiblyAffectedByAllOpen() ?: false) ->
|
||||
clsDelegate.hasModifierProperty(name)
|
||||
dummyDelegate != null -> {
|
||||
when {
|
||||
name in visibilityModifiers && isMethodOverride() ->
|
||||
@@ -90,6 +95,10 @@ private class KtLightMemberModifierList(
|
||||
else -> clsDelegate.hasModifierProperty(name)
|
||||
}
|
||||
|
||||
override fun hasExplicitModifier(name: String) =
|
||||
// kotlin methods can't be truly default atm, that way we can avoid being reported on by diagnostics, namely android lint
|
||||
if (name == PsiModifier.DEFAULT) false else super.hasExplicitModifier(name)
|
||||
|
||||
private fun isMethodOverride() = owner is KtLightMethod && owner.kotlinOrigin?.hasModifier(KtTokens.OVERRIDE_KEYWORD) ?: false
|
||||
|
||||
private fun isImplementationInInterface()
|
||||
|
||||
@@ -20,10 +20,13 @@ import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||
import com.intellij.psi.scope.PsiScopeProcessor
|
||||
import com.intellij.psi.util.*
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.builder.*
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.builder.MemberIndex
|
||||
import org.jetbrains.kotlin.asJava.builder.memberIndex
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.propertyNameByAccessor
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
@@ -93,7 +96,7 @@ class KtLightMethodImpl private constructor(
|
||||
nameExpression.replace(KtPsiFactory(this).createStringTemplate(name))
|
||||
}
|
||||
else {
|
||||
val toRename = kotlinOrigin as? PsiNamedElement ?: throwCanNotModify()
|
||||
val toRename = kotlinOrigin as? PsiNamedElement ?: cannotModify()
|
||||
toRename.setName(newNameForOrigin)
|
||||
}
|
||||
return this
|
||||
@@ -104,12 +107,9 @@ class KtLightMethodImpl private constructor(
|
||||
if (it.isValid) {
|
||||
it.delete()
|
||||
}
|
||||
} ?: throwCanNotModify()
|
||||
} ?: cannotModify()
|
||||
}
|
||||
|
||||
// TODO: add message
|
||||
private fun throwCanNotModify(): Nothing = throw IncorrectOperationException()
|
||||
|
||||
override fun getModifierList(): PsiModifierList {
|
||||
if (calculatingReturnType.get() == true) {
|
||||
return KotlinJavaPsiFacade.getInstance(project).emptyModifierList
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.psi.*
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.annotations.Nullable
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -187,8 +188,7 @@ class KtLightAnnotationForSourceEntry(
|
||||
|
||||
override fun hashCode() = kotlinOrigin.hashCode()
|
||||
|
||||
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?): T
|
||||
= clsDelegate.setDeclaredAttributeValue(attributeName, value)
|
||||
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify()
|
||||
}
|
||||
|
||||
class KtLightNonSourceAnnotation(
|
||||
@@ -196,8 +196,7 @@ class KtLightNonSourceAnnotation(
|
||||
): KtLightAbstractAnnotation(parent, { clsDelegate }) {
|
||||
override val kotlinOrigin: KtAnnotationEntry? get() = null
|
||||
override fun getQualifiedName() = clsDelegate.qualifiedName
|
||||
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?)
|
||||
= clsDelegate.setDeclaredAttributeValue(attributeName, value)
|
||||
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify()
|
||||
override fun findAttributeValue(attributeName: String?) = clsDelegate.findAttributeValue(attributeName)
|
||||
override fun findDeclaredAttributeValue(attributeName: String?) = clsDelegate.findDeclaredAttributeValue(attributeName)
|
||||
}
|
||||
@@ -244,8 +243,6 @@ class KtLightNullabilityAnnotation(member: KtLightElement<*, PsiModifierListOwne
|
||||
override fun findDeclaredAttributeValue(attributeName: String?) = null
|
||||
}
|
||||
|
||||
private fun cannotModify(): Nothing = error("Cannot modify") // TODO: meaningful message?
|
||||
|
||||
internal fun isNullabilityAnnotation(qualifiedName: String?) = qualifiedName in backendNullabilityAnnotations
|
||||
|
||||
private val backendNullabilityAnnotations = arrayOf(Nullable::class.java.name, NotNull::class.java.name)
|
||||
@@ -92,7 +92,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
findClassesAndObjects(qualifiedName, scope, answer);
|
||||
|
||||
answer.addAll(lightClassGenerationSupport.getFacadeClasses(qualifiedName, scope));
|
||||
answer.addAll(lightClassGenerationSupport.getMultifilePartClasses(qualifiedName, scope));
|
||||
answer.addAll(lightClassGenerationSupport.getKotlinInternalClasses(qualifiedName, scope));
|
||||
|
||||
return sortByClasspath(answer, scope).toArray(new PsiClass[answer.size()]);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.asJava
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotationForSourceEntry
|
||||
|
||||
@@ -64,15 +64,23 @@ internal class ExplicitReceiverScopeTowerProcessor<C: Candidate>(
|
||||
}
|
||||
|
||||
private fun resolveAsMember(): Collection<C> {
|
||||
val members =
|
||||
MemberScopeTowerLevel(scopeTower, explicitReceiver)
|
||||
.collectCandidates(null).filter { !it.requiresExtensionReceiver }
|
||||
return members.map { candidateFactory.createCandidate(it, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null) }
|
||||
val members = mutableListOf<C>()
|
||||
for (memberCandidate in MemberScopeTowerLevel(scopeTower, explicitReceiver).collectCandidates(null)) {
|
||||
if (!memberCandidate.requiresExtensionReceiver) {
|
||||
members.add(candidateFactory.createCandidate(memberCandidate, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null))
|
||||
}
|
||||
}
|
||||
return members
|
||||
}
|
||||
|
||||
private fun resolveAsExtension(level: ScopeTowerLevel): Collection<C> {
|
||||
val extensions = level.collectCandidates(explicitReceiver).filter { it.requiresExtensionReceiver }
|
||||
return extensions.map { candidateFactory.createCandidate(it, ExplicitReceiverKind.EXTENSION_RECEIVER, extensionReceiver = explicitReceiver) }
|
||||
val extensions = mutableListOf<C>()
|
||||
for (extensionCandidate in level.collectCandidates(explicitReceiver)) {
|
||||
if (extensionCandidate.requiresExtensionReceiver) {
|
||||
extensions.add(candidateFactory.createCandidate(extensionCandidate, ExplicitReceiverKind.EXTENSION_RECEIVER, extensionReceiver = explicitReceiver))
|
||||
}
|
||||
}
|
||||
return extensions
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,9 +93,12 @@ private class QualifierScopeTowerProcessor<C: Candidate>(
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
if (data != TowerData.Empty) return emptyList()
|
||||
|
||||
val staticMembers = QualifierScopeTowerLevel(scopeTower, qualifier).collectCandidates(null)
|
||||
.filter { !it.requiresExtensionReceiver }
|
||||
.map { candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) }
|
||||
val staticMembers = mutableListOf<C>()
|
||||
for (towerCandidate in QualifierScopeTowerLevel(scopeTower, qualifier).collectCandidates(null)) {
|
||||
if (!towerCandidate.requiresExtensionReceiver) {
|
||||
staticMembers.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null))
|
||||
}
|
||||
}
|
||||
return staticMembers
|
||||
}
|
||||
}
|
||||
@@ -99,19 +110,21 @@ private class NoExplicitReceiverScopeTowerProcessor<C: Candidate>(
|
||||
override fun simpleProcess(data: TowerData): Collection<C>
|
||||
= when(data) {
|
||||
is TowerData.TowerLevel -> {
|
||||
data.level.collectCandidates(null).filter { !it.requiresExtensionReceiver }.map {
|
||||
candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null)
|
||||
val result = mutableListOf<C>()
|
||||
for (towerCandidate in data.level.collectCandidates(null)) {
|
||||
if (!towerCandidate.requiresExtensionReceiver) {
|
||||
result.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null))
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
is TowerData.BothTowerLevelAndImplicitReceiver -> {
|
||||
val result = mutableListOf<C>()
|
||||
|
||||
data.level.collectCandidates(data.implicitReceiver).filter { it.requiresExtensionReceiver }.forEach {
|
||||
result.add(
|
||||
candidateFactory.createCandidate(
|
||||
it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver))
|
||||
for (towerCandidate in data.level.collectCandidates(data.implicitReceiver)) {
|
||||
if (towerCandidate.requiresExtensionReceiver) {
|
||||
result.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver))
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
else -> emptyList()
|
||||
|
||||
25
compiler/testData/asJava/lightClasses/ideRegression/AllOpenAnnotatedClasses.java
vendored
Normal file
25
compiler/testData/asJava/lightClasses/ideRegression/AllOpenAnnotatedClasses.java
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
@test.AllOpen
|
||||
public class C {
|
||||
private final int p;
|
||||
|
||||
public void f() { /* compiled code */ }
|
||||
|
||||
public void g() { /* compiled code */ }
|
||||
|
||||
public int getP() { /* compiled code */ }
|
||||
|
||||
public C() { /* compiled code */ }
|
||||
|
||||
public static final class D {
|
||||
public final void z() { /* compiled code */ }
|
||||
|
||||
public D() { /* compiled code */ }
|
||||
}
|
||||
|
||||
@test.AllOpen
|
||||
public static class H {
|
||||
public void j() { /* compiled code */ }
|
||||
|
||||
public H() { /* compiled code */ }
|
||||
}
|
||||
}
|
||||
26
compiler/testData/asJava/lightClasses/ideRegression/AllOpenAnnotatedClasses.kt
vendored
Normal file
26
compiler/testData/asJava/lightClasses/ideRegression/AllOpenAnnotatedClasses.kt
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// test.C
|
||||
package test
|
||||
|
||||
annotation class AllOpen
|
||||
|
||||
@AllOpen
|
||||
class C {
|
||||
fun f() {}
|
||||
|
||||
fun g() {}
|
||||
|
||||
val p: Int
|
||||
|
||||
class D {
|
||||
fun z() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@AllOpen
|
||||
class H {
|
||||
fun j() {}
|
||||
}
|
||||
}
|
||||
|
||||
// LAZINESS:NoLaziness
|
||||
38
compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.java
vendored
Normal file
38
compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.java
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
public final class Container {
|
||||
public Container() { /* compiled code */ }
|
||||
|
||||
public static final class MyString implements java.lang.CharSequence {
|
||||
public int getLength() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public error.NonExistentClass chars() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public error.NonExistentClass codePoints() { /* compiled code */ }
|
||||
|
||||
public char get(int index) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public java.lang.CharSequence subSequence(int startIndex, int endIndex) { /* compiled code */ }
|
||||
|
||||
public MyString() { /* compiled code */ }
|
||||
}
|
||||
|
||||
public static final class MyNumber extends java.lang.Number {
|
||||
public byte toByte() { /* compiled code */ }
|
||||
|
||||
public char toChar() { /* compiled code */ }
|
||||
|
||||
public double toDouble() { /* compiled code */ }
|
||||
|
||||
public float toFloat() { /* compiled code */ }
|
||||
|
||||
public int toInt() { /* compiled code */ }
|
||||
|
||||
public long toLong() { /* compiled code */ }
|
||||
|
||||
public short toShort() { /* compiled code */ }
|
||||
|
||||
public MyNumber() { /* compiled code */ }
|
||||
}
|
||||
}
|
||||
47
compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.kt
vendored
Normal file
47
compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.kt
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// p1.Container
|
||||
package p1
|
||||
|
||||
class Container {
|
||||
class MyString : CharSequence {
|
||||
override val length: Int
|
||||
get() = 0
|
||||
|
||||
override fun chars(): IntStream = error("")
|
||||
|
||||
override fun codePoints(): IntStream = error("")
|
||||
|
||||
override fun get(index: Int): Char = 'c'
|
||||
|
||||
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = MyString()
|
||||
}
|
||||
|
||||
class MyNumber : Number {
|
||||
override fun toByte(): Byte {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun toChar(): Char {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun toDouble(): Double {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun toFloat(): Float {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun toInt(): Int {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun toLong(): Long {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun toShort(): Short {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
5
compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.java
vendored
Normal file
5
compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.java
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
public final class TypeHierarchyMap <TValue> implements java.util.Map<java.lang.Class<?>,TValue>, kotlin.collections.Map<java.lang.Class<?>,TValue>, kotlin.jvm.internal.markers.KMappedMarker {
|
||||
public boolean containsKey(@org.jetbrains.annotations.NotNull java.lang.Class key) { /* compiled code */ }
|
||||
|
||||
public TypeHierarchyMap() { /* compiled code */ }
|
||||
}
|
||||
8
compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt
vendored
Normal file
8
compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// p1.TypeHierarchyMap
|
||||
package p1
|
||||
|
||||
class TypeHierarchyMap<TValue> : Map<Class<*>, TValue> {
|
||||
override fun containsKey(key: Class<*>): Boolean {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
43
compiler/testData/asJava/lightClasses/ideRegression/ImplementingMutableSet.java
vendored
Normal file
43
compiler/testData/asJava/lightClasses/ideRegression/ImplementingMutableSet.java
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
public final class SmartSet <T> extends kotlin.collections.AbstractSet<T> implements java.util.Set<T>, kotlin.collections.MutableSet<T>, kotlin.jvm.internal.markers.KMutableSet {
|
||||
private java.lang.Object data;
|
||||
private int size;
|
||||
private static final int ARRAY_THRESHOLD = 5;
|
||||
public static final SmartSet.Companion Companion;
|
||||
|
||||
public int getSize() { /* compiled code */ }
|
||||
|
||||
public void setSize(int i) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public java.util.Iterator<T> iterator() { /* compiled code */ }
|
||||
|
||||
public boolean add(T element) { /* compiled code */ }
|
||||
|
||||
public void clear() { /* compiled code */ }
|
||||
|
||||
public boolean contains(java.lang.Object element) { /* compiled code */ }
|
||||
|
||||
private SmartSet() { /* compiled code */ }
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static final <T> SmartSet<T> create() { /* compiled code */ }
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static final <T> SmartSet<T> create(@org.jetbrains.annotations.NotNull java.util.Collection<? extends T> set) { /* compiled code */ }
|
||||
|
||||
public static final class Companion {
|
||||
private final int getARRAY_THRESHOLD() { /* compiled code */ }
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final <T> SmartSet<T> create() { /* compiled code */ }
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final <T> SmartSet<T> create(@org.jetbrains.annotations.NotNull java.util.Collection<? extends T> set) { /* compiled code */ }
|
||||
|
||||
private Companion() { /* compiled code */ }
|
||||
}
|
||||
}
|
||||
35
compiler/testData/asJava/lightClasses/ideRegression/ImplementingMutableSet.kt
vendored
Normal file
35
compiler/testData/asJava/lightClasses/ideRegression/ImplementingMutableSet.kt
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// SmartSet
|
||||
|
||||
class SmartSet<T> private constructor() : AbstractSet<T>(), MutableSet<T> {
|
||||
companion object {
|
||||
private val ARRAY_THRESHOLD = 5
|
||||
|
||||
@JvmStatic
|
||||
fun <T> create() = SmartSet<T>()
|
||||
|
||||
@JvmStatic
|
||||
fun <T> create(set: Collection<T>): SmartSet<T> = TODO()
|
||||
}
|
||||
|
||||
private var data: Any? = null
|
||||
|
||||
override var size: Int = 0
|
||||
|
||||
|
||||
|
||||
override fun iterator(): MutableIterator<T> = TODO()
|
||||
|
||||
override fun add(element: T): Boolean = TODO()
|
||||
|
||||
override fun clear() {
|
||||
data = null
|
||||
size = 0
|
||||
}
|
||||
|
||||
override fun contains(element: T): Boolean = when {
|
||||
size == 0 -> false
|
||||
size == 1 -> data == element
|
||||
size < ARRAY_THRESHOLD -> element in data as Array<T>
|
||||
else -> element in data as Set<T>
|
||||
}
|
||||
}
|
||||
6
compiler/testData/cli/js/jsExtraHelp.out
vendored
6
compiler/testData/cli/js/jsExtraHelp.out
vendored
@@ -1,6 +1,8 @@
|
||||
Usage: kotlinc-js <options> <source files>
|
||||
where advanced options include:
|
||||
-Xtypedarrays Translate primitive arrays to JS typed arrays
|
||||
-Xtyped-arrays Translate primitive arrays to JS typed arrays
|
||||
-Xfriend-modules-disabled Disable internal declaration export
|
||||
-Xfriend-modules=<path> Paths to friend modules
|
||||
-Xno-inline Disable method inlining
|
||||
-Xrepeat=<count> Repeat compilation (for performance analysis)
|
||||
-Xskip-metadata-version-check Load classes with bad metadata version anyway (incl. pre-release classes)
|
||||
@@ -14,4 +16,4 @@ where advanced options include:
|
||||
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
|
||||
|
||||
Advanced options are non-standard and may be changed or removed without any notice.
|
||||
OK
|
||||
OK
|
||||
4
compiler/testData/cli/jvm/javaSrcWrongPackage.args
vendored
Normal file
4
compiler/testData/cli/jvm/javaSrcWrongPackage.args
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
$TESTDATA_DIR$/javaSrcWrongPackage.kt
|
||||
$TESTDATA_DIR$/javaSrcWrongPackage
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
1
compiler/testData/cli/jvm/javaSrcWrongPackage.kt
vendored
Normal file
1
compiler/testData/cli/jvm/javaSrcWrongPackage.kt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
fun test(): A.Nested = A().nested()
|
||||
7
compiler/testData/cli/jvm/javaSrcWrongPackage.out
vendored
Normal file
7
compiler/testData/cli/jvm/javaSrcWrongPackage.out
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
compiler/testData/cli/jvm/javaSrcWrongPackage.kt:1:13: error: unresolved reference: A
|
||||
fun test(): A.Nested = A().nested()
|
||||
^
|
||||
compiler/testData/cli/jvm/javaSrcWrongPackage.kt:1:24: error: unresolved reference: A
|
||||
fun test(): A.Nested = A().nested()
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
9
compiler/testData/cli/jvm/javaSrcWrongPackage/A.java
vendored
Normal file
9
compiler/testData/cli/jvm/javaSrcWrongPackage/A.java
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
package foo;
|
||||
|
||||
public class A {
|
||||
public Nested nested() {
|
||||
return new Nested();
|
||||
}
|
||||
|
||||
public static class Nested {}
|
||||
}
|
||||
11
compiler/testData/cli/jvm/singleJavaFileRoots.args
vendored
Normal file
11
compiler/testData/cli/jvm/singleJavaFileRoots.args
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
$TESTDATA_DIR$/singleJavaFileRoots/test.kt
|
||||
$TESTDATA_DIR$/singleJavaFileRoots/DefaultPackage.java
|
||||
$TESTDATA_DIR$/singleJavaFileRoots/lib/A.java
|
||||
$TESTDATA_DIR$/singleJavaFileRoots/lib/B.java
|
||||
$TESTDATA_DIR$/singleJavaFileRoots/lib/ext/SeveralClasses.java
|
||||
$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/ClassClass.java
|
||||
$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/InterfaceClass.java
|
||||
$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/EnumClass.java
|
||||
$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/AnnotationClass.java
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user