mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-12 08:31:33 +00:00
Compare commits
223 Commits
rr/mitropo
...
build-1.3.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75987697db | ||
|
|
1c93018db4 | ||
|
|
6fa26c5356 | ||
|
|
e97009bd49 | ||
|
|
6ae156c8a4 | ||
|
|
595d55707c | ||
|
|
9fbc71475b | ||
|
|
a13c744533 | ||
|
|
f2f1e923ee | ||
|
|
0905c6ba27 | ||
|
|
0ebe31af73 | ||
|
|
846fb60c91 | ||
|
|
ce36fc594f | ||
|
|
9e6db690d5 | ||
|
|
1702c8df25 | ||
|
|
88fcbdd079 | ||
|
|
8015483db6 | ||
|
|
e644c05b31 | ||
|
|
1220ef51b5 | ||
|
|
624a4802b4 | ||
|
|
7aef1a9073 | ||
|
|
774b5408b6 | ||
|
|
ac867bb063 | ||
|
|
9583b05160 | ||
|
|
a0e3340a03 | ||
|
|
7b68e5b74e | ||
|
|
debc248a78 | ||
|
|
297f5eefb2 | ||
|
|
1751e7ca78 | ||
|
|
30b5535dc1 | ||
|
|
973622bc60 | ||
|
|
cfa3422644 | ||
|
|
00a4365752 | ||
|
|
cfd030ac8d | ||
|
|
6230af0f3b | ||
|
|
0fa22c3327 | ||
|
|
9ba0202d59 | ||
|
|
a967c47d1c | ||
|
|
e8fea9d4ef | ||
|
|
cc5cf643a8 | ||
|
|
20a631a838 | ||
|
|
c6e5a5d72a | ||
|
|
a6bad98241 | ||
|
|
7cf16d9af6 | ||
|
|
59eeb287c9 | ||
|
|
2e14313bc8 | ||
|
|
1872b3dd1d | ||
|
|
4c3ac350c9 | ||
|
|
44f8e92c6f | ||
|
|
f279ae5576 | ||
|
|
e4f4619f37 | ||
|
|
bff63fe902 | ||
|
|
7b6cd7305a | ||
|
|
7640718805 | ||
|
|
8830387118 | ||
|
|
908b8a4b4e | ||
|
|
3430aa24ec | ||
|
|
f3b206227a | ||
|
|
a1d2a5ac82 | ||
|
|
fc33aa9552 | ||
|
|
2c0ecedb5a | ||
|
|
3ba7339a46 | ||
|
|
e449f18fc0 | ||
|
|
7def3c19dc | ||
|
|
fc46a7704c | ||
|
|
4d06db6852 | ||
|
|
883dbfe138 | ||
|
|
d6f388845d | ||
|
|
2e9a596b53 | ||
|
|
da86804719 | ||
|
|
2bbbf9677f | ||
|
|
543671227d | ||
|
|
5b5262eedf | ||
|
|
42ad282dee | ||
|
|
23b0143688 | ||
|
|
1e782311e5 | ||
|
|
7eae8ccc09 | ||
|
|
375e46b91f | ||
|
|
cfdfdcb954 | ||
|
|
819c6e5a51 | ||
|
|
2b1d2ea2fe | ||
|
|
e20444e441 | ||
|
|
c71c2fba05 | ||
|
|
fb5095f94e | ||
|
|
ac77446657 | ||
|
|
7c66d0e3a6 | ||
|
|
c7634fb41a | ||
|
|
d634db2d82 | ||
|
|
43482f60ae | ||
|
|
b940b64d06 | ||
|
|
72e42ba2cb | ||
|
|
20766dce65 | ||
|
|
34199c5d92 | ||
|
|
816976035b | ||
|
|
8df408122f | ||
|
|
f349b92896 | ||
|
|
f221a6794b | ||
|
|
037b7a5f5e | ||
|
|
39af8f3994 | ||
|
|
fd192f811e | ||
|
|
d83e2afcdf | ||
|
|
45e5013097 | ||
|
|
24aa636283 | ||
|
|
2884cfc9e4 | ||
|
|
2cc7bab0ff | ||
|
|
f3bef7e48b | ||
|
|
7717921574 | ||
|
|
08180d95e9 | ||
|
|
318f8e2891 | ||
|
|
724fa51fb4 | ||
|
|
68aa525877 | ||
|
|
51c4a10276 | ||
|
|
75572882a3 | ||
|
|
b731b02eda | ||
|
|
f5d28808c8 | ||
|
|
5b206eeee6 | ||
|
|
f29926006b | ||
|
|
9dc11b2dd7 | ||
|
|
4422fd220a | ||
|
|
0731ad4bf0 | ||
|
|
7dc3797e85 | ||
|
|
4c81b4d4a7 | ||
|
|
2c907e800a | ||
|
|
fe16ac8628 | ||
|
|
a11dd0a7b5 | ||
|
|
3bd19503b0 | ||
|
|
c52204359b | ||
|
|
51fc596aa9 | ||
|
|
0cfbd1a27f | ||
|
|
5da0d8f060 | ||
|
|
d0969e77dd | ||
|
|
b4101ef2ae | ||
|
|
edd4f283c6 | ||
|
|
7d07329292 | ||
|
|
1eadec5432 | ||
|
|
0a33859eb2 | ||
|
|
9a0f3f9e57 | ||
|
|
2a7bb8d13e | ||
|
|
fc9b41a05c | ||
|
|
ac16907f1c | ||
|
|
c24bbff948 | ||
|
|
410123d0f7 | ||
|
|
04cb2265d8 | ||
|
|
d5e1fc24e0 | ||
|
|
7725f0d1d7 | ||
|
|
6e3494d83c | ||
|
|
3cfee99ac6 | ||
|
|
68cd113d83 | ||
|
|
8de34046a8 | ||
|
|
a2be50a223 | ||
|
|
700a7c68eb | ||
|
|
d7d066d081 | ||
|
|
a30b4af7a4 | ||
|
|
55097c09a0 | ||
|
|
09c97d7a18 | ||
|
|
9ac928aa1b | ||
|
|
5322dbe3fe | ||
|
|
3927e7615a | ||
|
|
3a3bd4826f | ||
|
|
148ac0471d | ||
|
|
2eba1714bc | ||
|
|
758db84e53 | ||
|
|
75f8025d6a | ||
|
|
e41d8ca122 | ||
|
|
d0b71643b7 | ||
|
|
80d1c9a7de | ||
|
|
4b060b68fe | ||
|
|
2d10730233 | ||
|
|
53a2fb7302 | ||
|
|
09d0cba192 | ||
|
|
a5b19826e7 | ||
|
|
863be9369a | ||
|
|
92e125413d | ||
|
|
6aebc695ec | ||
|
|
1bb75ac2ec | ||
|
|
1e2115ba83 | ||
|
|
34dd6062fd | ||
|
|
e7cea0239a | ||
|
|
962a52ef0d | ||
|
|
6a50cd8a11 | ||
|
|
b96d77db63 | ||
|
|
fe9287a20e | ||
|
|
d30eb186fd | ||
|
|
b8c0d0f589 | ||
|
|
e6b1e1df3a | ||
|
|
f7d4aae815 | ||
|
|
da5bfd6bea | ||
|
|
d0c59dc73f | ||
|
|
79b9f2fdf2 | ||
|
|
1207568c60 | ||
|
|
0bcec43b9a | ||
|
|
0c5ccbe6eb | ||
|
|
d3d027bc2d | ||
|
|
278afe0691 | ||
|
|
6854ed319b | ||
|
|
07d3842de8 | ||
|
|
c66ce278e2 | ||
|
|
9a76ea227d | ||
|
|
ecbe37085b | ||
|
|
5dc88796d9 | ||
|
|
bf3debdfb2 | ||
|
|
9bb9bdd0a5 | ||
|
|
5bf88069db | ||
|
|
f874b8aebd | ||
|
|
2873aaf4e2 | ||
|
|
daab8d4e14 | ||
|
|
df648dbb06 | ||
|
|
c4d52e0a80 | ||
|
|
6988ab0a4f | ||
|
|
630502e17d | ||
|
|
0cc6ece8dc | ||
|
|
b6dcebb08e | ||
|
|
196193c238 | ||
|
|
e04c080e89 | ||
|
|
b8f92714ac | ||
|
|
ac052ce52a | ||
|
|
83934bfd14 | ||
|
|
7214d36a49 | ||
|
|
43eb3e4042 | ||
|
|
6b6c3e7ff3 | ||
|
|
3ab2da1226 | ||
|
|
d51be4cd77 | ||
|
|
68889d839d |
1
.idea/inspectionProfiles/idea_default.xml
generated
1
.idea/inspectionProfiles/idea_default.xml
generated
@@ -115,6 +115,7 @@
|
||||
<Problem reference="com.intellij.util.AstLoadingFilter" reason="Absent in 181. Almost all methods were renamed in 183. Use org.jetbrains.kotlin.util.AstLoadingFilter instead." />
|
||||
<Problem reference="com.intellij.testFramework.codeInsight.hierarchy.HierarchyViewTestFixture" reason="Absent in <= 181. Use org.jetbrains.kotlin.test.HierarchyViewTestFixture instead." />
|
||||
<Problem reference="org.jetbrains.kotlin.test.HierarchyViewTestFixtureCompat" reason="Do not use the wrapper for 181 directly. Use org.jetbrains.kotlin.test.HierarchyViewTestFixture instead." />
|
||||
<Problem reference="com.intellij.psi.codeStyle.CodeStyleSettingsProvider" reason="Additional method is introduced in 183 instead of deprecated one. Use CodeStyleSettingsProviderCompat instead." />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
|
||||
7203
ChangeLog.md
7203
ChangeLog.md
File diff suppressed because it is too large
Load Diff
@@ -479,6 +479,7 @@ tasks {
|
||||
":compiler:container:test",
|
||||
":compiler:tests-java8:test",
|
||||
":compiler:tests-spec:remoteRunTests")
|
||||
dependsOn(":plugins:jvm-abi-gen:test")
|
||||
}
|
||||
|
||||
create("jsCompilerTest") {
|
||||
|
||||
@@ -15,6 +15,7 @@ fun Project.smartJavaExec(configure: JavaExec.() -> Unit) = task<JavaExec> javaE
|
||||
val classpath = classpath
|
||||
val main = main
|
||||
dependsOn(classpath)
|
||||
inputs.files(classpath)
|
||||
inputs.property("main", main)
|
||||
doFirst {
|
||||
val classPathString = classpath.joinToString(" ") { project.file(it).toURI().toString() }
|
||||
|
||||
@@ -1217,8 +1217,16 @@ public class AsmUtil {
|
||||
return JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName();
|
||||
}
|
||||
|
||||
public static void putJavaLangClassInstance(@NotNull InstructionAdapter v, @NotNull Type type) {
|
||||
if (isPrimitive(type)) {
|
||||
public static void putJavaLangClassInstance(
|
||||
@NotNull InstructionAdapter v,
|
||||
@NotNull Type type,
|
||||
@Nullable KotlinType kotlinType,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
if (kotlinType != null && InlineClassesUtilsKt.isInlineClassType(kotlinType)) {
|
||||
v.aconst(boxType(type, kotlinType, state));
|
||||
}
|
||||
else if (isPrimitive(type)) {
|
||||
v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;");
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -40,7 +40,16 @@ public class ClassBuilderMode {
|
||||
* Full function bodies
|
||||
*/
|
||||
public final static ClassBuilderMode FULL = new ClassBuilderMode(
|
||||
/* bodies = */ true,
|
||||
/* bodies = */ true,
|
||||
/* metadata = */ true,
|
||||
/* sourceRetention = */ false,
|
||||
/* generateMultiFileFacadePartClasses = */ true);
|
||||
|
||||
/**
|
||||
* ABI for compilation (non-private signatures + inline function bodies)
|
||||
*/
|
||||
public final static ClassBuilderMode ABI = new ClassBuilderMode(
|
||||
/* bodies = */ true,
|
||||
/* metadata = */ true,
|
||||
/* sourceRetention = */ false,
|
||||
/* generateMultiFileFacadePartClasses = */ true);
|
||||
|
||||
@@ -245,7 +245,9 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
DescriptorSerializer serializer =
|
||||
DescriptorSerializer.createForLambda(new JvmSerializerExtension(v.getSerializationBindings(), state));
|
||||
|
||||
ProtoBuf.Function functionProto = serializer.functionProto(freeLambdaDescriptor).build();
|
||||
ProtoBuf.Function.Builder builder = serializer.functionProto(freeLambdaDescriptor);
|
||||
if (builder == null) return;
|
||||
ProtoBuf.Function functionProto = builder.build();
|
||||
|
||||
WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0, av -> {
|
||||
writeAnnotationData(av, serializer, functionProto);
|
||||
@@ -400,7 +402,9 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
|
||||
if (container instanceof ClassDescriptor) {
|
||||
// TODO: would it work for arrays?
|
||||
putJavaLangClassInstance(iv, state.getTypeMapper().mapClass((ClassDescriptor) container));
|
||||
SimpleType containerKotlinType = ((ClassDescriptor) container).getDefaultType();
|
||||
Type containerType = state.getTypeMapper().mapClass((ClassDescriptor) container);
|
||||
putJavaLangClassInstance(iv, containerType, containerKotlinType, state);
|
||||
}
|
||||
else if (container instanceof PackageFragmentDescriptor) {
|
||||
iv.aconst(state.getTypeMapper().mapOwner(descriptor));
|
||||
|
||||
@@ -454,6 +454,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return typeMapper.mapType(type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapTypeAsDeclaration(@NotNull KotlinType type) {
|
||||
return typeMapper.mapTypeAsDeclaration(type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type expressionType(@Nullable KtExpression expression) {
|
||||
return CodegenUtilKt.asmType(expression, typeMapper, bindingContext);
|
||||
@@ -1881,7 +1886,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor getSuperCallTarget(@NotNull Call call) {
|
||||
public ClassDescriptor getSuperCallTarget(@NotNull Call call) {
|
||||
KtSuperExpression superExpression = CallResolverUtilKt.getSuperCallExpression(call);
|
||||
return superExpression == null ? null : getSuperCallLabelTarget(context, superExpression);
|
||||
}
|
||||
@@ -2051,7 +2056,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
isDefaultAccessor(propertyDescriptor.getGetter()) && isDefaultAccessor(propertyDescriptor.getSetter())))) {
|
||||
fieldAccessorKind = JvmCodegenUtil.isDebuggerContext(context) ? AccessorKind.NORMAL : AccessorKind.IN_CLASS_COMPANION;
|
||||
}
|
||||
else if ((syntheticBackingField &&
|
||||
else //noinspection ConstantConditions
|
||||
if ((syntheticBackingField &&
|
||||
context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration)) {
|
||||
fieldAccessorKind = AccessorKind.FIELD_FROM_LOCAL;
|
||||
}
|
||||
@@ -2077,17 +2083,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
boolean skipPropertyAccessors;
|
||||
|
||||
PropertyDescriptor originalPropertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor);
|
||||
boolean directAccessToGetter = couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context,
|
||||
state.getShouldInlineConstVals());
|
||||
boolean directAccessToSetter = couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context,
|
||||
state.getShouldInlineConstVals());
|
||||
boolean directAccessToGetter =
|
||||
couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context, state.getShouldInlineConstVals());
|
||||
boolean directAccessToSetter =
|
||||
couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context, state.getShouldInlineConstVals());
|
||||
|
||||
if (fieldAccessorKind == AccessorKind.LATEINIT_INTRINSIC) {
|
||||
skipPropertyAccessors = !isPrivateProperty || context.getClassOrPackageParentContext() == backingFieldContext;
|
||||
skipPropertyAccessors =
|
||||
(!isPrivateProperty || context.getClassOrPackageParentContext() == backingFieldContext) &&
|
||||
!isBackingFieldMovedFromCompanion;
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
propertyDescriptor = (AccessorForPropertyBackingField)
|
||||
backingFieldContext.getAccessor(propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget);
|
||||
if (isBackingFieldMovedFromCompanion && context.getContextDescriptor() instanceof AccessorForPropertyBackingField) {
|
||||
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getParentContext()
|
||||
.getAccessor(propertyDescriptor, AccessorKind.IN_CLASS_COMPANION, delegateType, superCallTarget);
|
||||
}
|
||||
else {
|
||||
propertyDescriptor =
|
||||
backingFieldContext.getAccessor(propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget);
|
||||
}
|
||||
}
|
||||
ownerDescriptor = propertyDescriptor;
|
||||
}
|
||||
@@ -2097,10 +2111,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
(directAccessToGetter && (!propertyDescriptor.isVar() || directAccessToSetter));
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
//noinspection ConstantConditions
|
||||
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(
|
||||
propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget
|
||||
);
|
||||
propertyDescriptor = backingFieldContext.getAccessor(propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget);
|
||||
assert propertyDescriptor instanceof AccessorForPropertyBackingField :
|
||||
"Unexpected accessor descriptor: " + propertyDescriptor;
|
||||
ownerDescriptor = propertyDescriptor;
|
||||
@@ -3117,7 +3128,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS);
|
||||
}
|
||||
|
||||
putJavaLangClassInstance(v, typeMapper.mapType(type));
|
||||
putJavaLangClassInstance(v, typeMapper.mapType(type), type, state);
|
||||
}
|
||||
|
||||
if (wrapIntoKClass) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
@@ -715,26 +716,23 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) {
|
||||
String name = thisType.getClassName();
|
||||
int indexOfLambdaOrdinal = name.lastIndexOf("$");
|
||||
if (indexOfLambdaOrdinal > 0) {
|
||||
int lambdaOrdinal = Integer.parseInt(name.substring(indexOfLambdaOrdinal + 1));
|
||||
String internalName = thisType.getInternalName();
|
||||
String lambdaLocalName = StringsKt.substringAfterLast(internalName, '/', internalName);
|
||||
|
||||
KtPureElement functionArgument = parentCodegen.element;
|
||||
String functionName = "unknown";
|
||||
if (functionArgument instanceof KtFunction) {
|
||||
ValueParameterDescriptor inlineArgumentDescriptor =
|
||||
InlineUtil.getInlineArgumentDescriptor((KtFunction) functionArgument, parentCodegen.bindingContext);
|
||||
if (inlineArgumentDescriptor != null) {
|
||||
functionName = inlineArgumentDescriptor.getContainingDeclaration().getName().asString();
|
||||
}
|
||||
KtPureElement functionArgument = parentCodegen.element;
|
||||
String functionName = "unknown";
|
||||
if (functionArgument instanceof KtFunction) {
|
||||
ValueParameterDescriptor inlineArgumentDescriptor =
|
||||
InlineUtil.getInlineArgumentDescriptor((KtFunction) functionArgument, parentCodegen.bindingContext);
|
||||
if (inlineArgumentDescriptor != null) {
|
||||
functionName = inlineArgumentDescriptor.getContainingDeclaration().getName().asString();
|
||||
}
|
||||
mv.visitLocalVariable(
|
||||
JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + lambdaOrdinal + "$" + functionName,
|
||||
Type.INT_TYPE.getDescriptor(), null,
|
||||
methodBegin, methodEnd,
|
||||
lambdaFakeIndex);
|
||||
}
|
||||
mv.visitLocalVariable(
|
||||
JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + "-" + functionName + "-" + lambdaLocalName,
|
||||
Type.INT_TYPE.getDescriptor(), null,
|
||||
methodBegin, methodEnd,
|
||||
lambdaFakeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
@@ -107,21 +108,22 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
|
||||
|
||||
JvmKotlinType type = genOrLoadOnStack(iv, context, propertyDescriptor, 0);
|
||||
Type asmType = type.getType();
|
||||
KotlinType kotlinType = type.getKotlinType();
|
||||
|
||||
if (asmType.getSort() == Type.ARRAY) {
|
||||
Type elementType = correctElementType(asmType);
|
||||
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
|
||||
iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;", false);
|
||||
asmType = JAVA_STRING_TYPE;
|
||||
kotlinType = DescriptorUtilsKt.getBuiltIns(function).getStringType();
|
||||
}
|
||||
else {
|
||||
if (elementType.getSort() != Type.CHAR) {
|
||||
iv.invokestatic("java/util/Arrays", "toString", "(" + asmType.getDescriptor() + ")Ljava/lang/String;", false);
|
||||
asmType = JAVA_STRING_TYPE;
|
||||
}
|
||||
else if (elementType.getSort() != Type.CHAR) {
|
||||
iv.invokestatic("java/util/Arrays", "toString", "(" + asmType.getDescriptor() + ")Ljava/lang/String;", false);
|
||||
asmType = JAVA_STRING_TYPE;
|
||||
kotlinType = DescriptorUtilsKt.getBuiltIns(function).getStringType();
|
||||
}
|
||||
}
|
||||
genInvokeAppendMethod(iv, asmType, type.getKotlinType(), typeMapper);
|
||||
genInvokeAppendMethod(iv, asmType, kotlinType, typeMapper);
|
||||
}
|
||||
|
||||
iv.aconst(")");
|
||||
|
||||
@@ -170,10 +170,10 @@ class ScriptCodegen private constructor(
|
||||
genFieldFromParam(typeMapper.mapClass(receiver), receiversParamIndex, name)
|
||||
}
|
||||
|
||||
scriptDescriptor.scriptEnvironmentProperties.forEachIndexed { envVarIndex, envVar ->
|
||||
scriptDescriptor.scriptProvidedProperties.forEachIndexed { envVarIndex, envVar ->
|
||||
val fieldClassType = typeMapper.mapType(envVar)
|
||||
val envVarParamIndex = frameMap.enterTemp(fieldClassType)
|
||||
val name = scriptContext.getEnvironmentVarName(envVarIndex)
|
||||
val name = scriptContext.getProvidedPropertyName(envVarIndex)
|
||||
genFieldFromParam(fieldClassType, envVarParamIndex, name)
|
||||
}
|
||||
|
||||
@@ -209,12 +209,12 @@ class ScriptCodegen private constructor(
|
||||
null
|
||||
)
|
||||
}
|
||||
for (envVarIndex in scriptDescriptor.scriptEnvironmentProperties.indices) {
|
||||
for (envVarIndex in scriptDescriptor.scriptProvidedProperties.indices) {
|
||||
classBuilder.newField(
|
||||
NO_ORIGIN,
|
||||
ACC_PUBLIC or ACC_FINAL,
|
||||
scriptContext.getEnvironmentVarName(envVarIndex),
|
||||
scriptContext.getEnvironmentVarType(envVarIndex).descriptor,
|
||||
scriptContext.getProvidedPropertyName(envVarIndex),
|
||||
scriptContext.getProvidedPropertyType(envVarIndex).descriptor,
|
||||
null,
|
||||
null
|
||||
)
|
||||
|
||||
@@ -728,15 +728,20 @@ public abstract class StackValue {
|
||||
@NotNull Field refWrapper,
|
||||
@NotNull VariableDescriptor variableDescriptor
|
||||
) {
|
||||
return new FieldForSharedVar(localType, classType, fieldName, refWrapper,
|
||||
variableDescriptor.isLateInit(), variableDescriptor.getName());
|
||||
return new FieldForSharedVar(
|
||||
localType, variableDescriptor.getType(), classType, fieldName, refWrapper,
|
||||
variableDescriptor.isLateInit(), variableDescriptor.getName()
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FieldForSharedVar fieldForSharedVar(@NotNull FieldForSharedVar field, @NotNull StackValue newReceiver) {
|
||||
Field oldReceiver = (Field) field.receiver;
|
||||
Field newSharedVarReceiver = field(oldReceiver, newReceiver);
|
||||
return new FieldForSharedVar(field.type, field.owner, field.name, newSharedVarReceiver, field.isLateinit, field.variableName);
|
||||
return new FieldForSharedVar(
|
||||
field.type, field.kotlinType,
|
||||
field.owner, field.name, newSharedVarReceiver, field.isLateinit, field.variableName
|
||||
);
|
||||
}
|
||||
|
||||
public static StackValue coercion(@NotNull StackValue value, @NotNull Type castType, @Nullable KotlinType castKotlinType) {
|
||||
@@ -880,6 +885,7 @@ public abstract class StackValue {
|
||||
// 2) call using callable reference: in this case it is not local, but rather captured value
|
||||
// 3) recursive call: we are in the middle of defining it, but, thankfully, we can simply call `this.invoke` to
|
||||
// create new coroutine
|
||||
// 4) Normal call, but the value is captured
|
||||
|
||||
// First, check whether this is a normal call
|
||||
int index = codegen.lookupLocalIndex(callee);
|
||||
@@ -893,24 +899,27 @@ public abstract class StackValue {
|
||||
Type calleeType = CodegenBinding.asmTypeForAnonymousClass(bindingContext, callee);
|
||||
if (codegen.context.hasThisDescriptor()) {
|
||||
ClassDescriptor thisDescriptor = codegen.context.getThisDescriptor();
|
||||
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, callee);
|
||||
if (thisDescriptor instanceof SyntheticClassDescriptorForLambda &&
|
||||
((SyntheticClassDescriptorForLambda) thisDescriptor).isCallableReference()) {
|
||||
// Call is inside a callable reference
|
||||
// if it is call to recursive local, just return this$0
|
||||
Boolean isRecursive = bindingContext.get(RECURSIVE_SUSPEND_CALLABLE_REFERENCE, thisDescriptor);
|
||||
if (isRecursive != null && isRecursive) {
|
||||
ClassDescriptor classDescriptor =
|
||||
bindingContext.get(CLASS_FOR_CALLABLE, callee);
|
||||
assert classDescriptor != null : "No CLASS_FOR_CALLABLE" + callee;
|
||||
return thisOrOuter(codegen, classDescriptor, false, false);
|
||||
}
|
||||
// Otherwise, just call constructor of the closure
|
||||
return codegen.findCapturedValue(callee);
|
||||
}
|
||||
if (classDescriptor == thisDescriptor) {
|
||||
// Recursive suspend local function, just call invoke on this, it will create new coroutine automatically
|
||||
codegen.v.visitVarInsn(ALOAD, 0);
|
||||
return onStack(calleeType);
|
||||
}
|
||||
}
|
||||
// Recursive suspend local function, just call invoke on this, it will create new coroutine automatically
|
||||
codegen.v.visitVarInsn(ALOAD, 0);
|
||||
return onStack(calleeType);
|
||||
// Otherwise, this is captured value
|
||||
return codegen.findCapturedValue(callee);
|
||||
}
|
||||
|
||||
private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) {
|
||||
@@ -1655,8 +1664,14 @@ public abstract class StackValue {
|
||||
|
||||
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD,
|
||||
backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
||||
if (!skipLateinitAssertion) {
|
||||
genNotNullAssertionForLateInitIfNeeded(v);
|
||||
if (!skipLateinitAssertion && descriptor.isLateInit()) {
|
||||
CallableMemberDescriptor contextDescriptor = codegen.context.getContextDescriptor();
|
||||
boolean isCompanionAccessor =
|
||||
contextDescriptor instanceof AccessorForPropertyBackingField &&
|
||||
((AccessorForPropertyBackingField) contextDescriptor).getAccessorKind() == AccessorKind.IN_CLASS_COMPANION;
|
||||
if (!isCompanionAccessor) {
|
||||
genNonNullAssertForLateinit(v, this.descriptor.getName().asString());
|
||||
}
|
||||
}
|
||||
coerceTo(type, kotlinType, v);
|
||||
}
|
||||
@@ -1689,6 +1704,19 @@ public abstract class StackValue {
|
||||
|
||||
coerce(typeOfValueOnStack, kotlinTypeOfValueOnStack, type, kotlinType, v);
|
||||
|
||||
// For non-private lateinit properties in companion object, the assertion is generated in the public getFoo method
|
||||
// in the companion and _not_ in the synthetic accessor access$getFoo$cp in the outer class. The reason is that this way,
|
||||
// the synthetic accessor can be reused for isInitialized checks, which require there to be no assertion.
|
||||
// For lateinit properties that are accessed via the backing field directly (or via the synthetic accessor, if the access
|
||||
// is from a different context), the assertion will be generated on each access, see KT-28331.
|
||||
if (descriptor instanceof AccessorForPropertyBackingField) {
|
||||
PropertyDescriptor property = ((AccessorForPropertyBackingField) descriptor).getCalleeDescriptor();
|
||||
if (!skipLateinitAssertion && property.isLateInit() && JvmAbi.isPropertyWithBackingFieldInOuterClass(property) &&
|
||||
!JvmCodegenUtil.couldUseDirectAccessToProperty(property, true, false, codegen.context, false)) {
|
||||
genNonNullAssertForLateinit(v, property.getName().asString());
|
||||
}
|
||||
}
|
||||
|
||||
KotlinType returnType = descriptor.getReturnType();
|
||||
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) {
|
||||
v.aconst(null);
|
||||
@@ -1727,12 +1755,6 @@ public abstract class StackValue {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void genNotNullAssertionForLateInitIfNeeded(@NotNull InstructionAdapter v) {
|
||||
if (!descriptor.isLateInit()) return;
|
||||
|
||||
StackValue.genNonNullAssertForLateinit(v, descriptor.getName().asString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(@NotNull StackValue rightSide, @NotNull InstructionAdapter v, boolean skipReceiver) {
|
||||
PropertySetterDescriptor setterDescriptor = descriptor.getSetter();
|
||||
@@ -1900,10 +1922,11 @@ public abstract class StackValue {
|
||||
final Name variableName;
|
||||
|
||||
public FieldForSharedVar(
|
||||
Type type, Type owner, String name, StackValue.Field receiver,
|
||||
Type type, KotlinType kotlinType,
|
||||
Type owner, String name, StackValue.Field receiver,
|
||||
boolean isLateinit, Name variableName
|
||||
) {
|
||||
super(type, null, false, false, receiver, receiver.canHaveSideEffects());
|
||||
super(type, kotlinType, false, false, receiver, receiver.canHaveSideEffects());
|
||||
|
||||
if (isLateinit && variableName == null) {
|
||||
throw new IllegalArgumentException("variableName should be non-null for captured lateinit variable " + name);
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
import org.jetbrains.org.objectweb.asm.tree.LocalVariableNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
|
||||
import org.jetbrains.org.objectweb.asm.util.Textifier;
|
||||
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getNodeText;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.wrapWithMaxLocalCalc;
|
||||
|
||||
public abstract class TransformationMethodVisitor extends MethodVisitor {
|
||||
|
||||
private final MethodNode methodNode;
|
||||
private final MethodVisitor delegate;
|
||||
|
||||
public TransformationMethodVisitor(
|
||||
@NotNull MethodVisitor delegate,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
) {
|
||||
super(Opcodes.ASM5);
|
||||
this.delegate = delegate;
|
||||
this.methodNode = new MethodNode(access, name, desc, signature, exceptions);
|
||||
this.methodNode.localVariables = new ArrayList<>(5);
|
||||
this.mv = wrapWithMaxLocalCalc(methodNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// force mv to calculate maxStack/maxLocals in case it didn't yet done
|
||||
if (methodNode.maxLocals <= 0 || methodNode.maxStack <= 0) {
|
||||
mv.visitMaxs(-1, -1);
|
||||
}
|
||||
|
||||
super.visitEnd();
|
||||
|
||||
try {
|
||||
if (shouldBeTransformed(methodNode)) {
|
||||
performTransformations(methodNode);
|
||||
}
|
||||
|
||||
methodNode.accept(new EndIgnoringMethodVisitorDecorator(Opcodes.ASM5, delegate));
|
||||
|
||||
|
||||
// In case of empty instructions list MethodNode.accept doesn't call visitLocalVariables of delegate
|
||||
// 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.localVariables != null)
|
||||
) {
|
||||
List<LocalVariableNode> localVariables = methodNode.localVariables;
|
||||
// visits local variables
|
||||
int n = localVariables == null ? 0 : localVariables.size();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
localVariables.get(i).accept(delegate);
|
||||
}
|
||||
}
|
||||
|
||||
delegate.visitEnd();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw new CompilationException("Couldn't transform method node:\n" + getNodeText(methodNode), t, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void performTransformations(@NotNull MethodNode methodNode);
|
||||
|
||||
/**
|
||||
* You can use it when you need to ignore visit end
|
||||
*/
|
||||
private static class EndIgnoringMethodVisitorDecorator extends MethodVisitor {
|
||||
public EndIgnoringMethodVisitorDecorator(int api, @NotNull MethodVisitor mv) {
|
||||
super(api, mv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TraceMethodVisitor getTraceMethodVisitorIfPossible() {
|
||||
TraceMethodVisitor traceMethodVisitor = new TraceMethodVisitor(new Textifier());
|
||||
try {
|
||||
methodNode.accept(traceMethodVisitor);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return traceMethodVisitor;
|
||||
}
|
||||
|
||||
private static boolean shouldBeTransformed(@NotNull MethodNode node) {
|
||||
return node.instructions.size() > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.util.Textifier
|
||||
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
import org.jetbrains.kotlin.codegen.inline.nodeText
|
||||
import org.jetbrains.kotlin.codegen.inline.wrapWithMaxLocalCalc
|
||||
|
||||
abstract class TransformationMethodVisitor(
|
||||
private val delegate: MethodVisitor,
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?,
|
||||
api: Int = Opcodes.ASM5
|
||||
) : MethodVisitor(api) {
|
||||
|
||||
private val methodNode = MethodNode(access, name, desc, signature, exceptions).apply {
|
||||
localVariables = ArrayList(5)
|
||||
}
|
||||
|
||||
val traceMethodVisitorIfPossible: TraceMethodVisitor?
|
||||
get() {
|
||||
val traceMethodVisitor = TraceMethodVisitor(Textifier())
|
||||
try {
|
||||
methodNode.accept(traceMethodVisitor)
|
||||
} catch (e: Throwable) {
|
||||
return null
|
||||
}
|
||||
|
||||
return traceMethodVisitor
|
||||
}
|
||||
|
||||
init {
|
||||
mv = wrapWithMaxLocalCalc(methodNode)
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
// force mv to calculate maxStack/maxLocals in case it didn't yet done
|
||||
if (methodNode.maxLocals <= 0 || methodNode.maxStack <= 0) {
|
||||
mv.visitMaxs(-1, -1)
|
||||
}
|
||||
|
||||
super.visitEnd()
|
||||
|
||||
try {
|
||||
if (shouldBeTransformed(methodNode)) {
|
||||
performTransformations(methodNode)
|
||||
}
|
||||
|
||||
methodNode.accept(EndIgnoringMethodVisitorDecorator(Opcodes.ASM5, delegate))
|
||||
|
||||
|
||||
// In case of empty instructions list MethodNode.accept doesn't call visitLocalVariables of delegate
|
||||
// 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 !is MethodNode || methodNode.localVariables != null)
|
||||
) {
|
||||
val localVariables = methodNode.localVariables
|
||||
// visits local variables
|
||||
val n = localVariables?.size ?: 0
|
||||
for (i in 0 until n) {
|
||||
localVariables!![i].accept(delegate)
|
||||
}
|
||||
}
|
||||
|
||||
delegate.visitEnd()
|
||||
} catch (t: Throwable) {
|
||||
throw CompilationException("Couldn't transform method node:\n" + methodNode.nodeText, t, null)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun performTransformations(methodNode: MethodNode)
|
||||
|
||||
/**
|
||||
* You can use it when you need to ignore visit end
|
||||
*/
|
||||
private class EndIgnoringMethodVisitorDecorator(api: Int, mv: MethodVisitor) : MethodVisitor(api, mv) {
|
||||
|
||||
override fun visitEnd() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldBeTransformed(node: MethodNode): Boolean {
|
||||
return node.instructions.size() > 0
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.FieldInfo
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
@@ -33,9 +32,8 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptEnvironmentDescriptor
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptProvidedPropertiesDescriptor
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class ScriptContext(
|
||||
val typeMapper: KotlinTypeMapper,
|
||||
@@ -76,25 +74,24 @@ class ScriptContext(
|
||||
private val ctorImplicitReceiversParametersStart =
|
||||
ctorValueParametersStart + (scriptDescriptor.getSuperClassNotAny()?.unsubstitutedPrimaryConstructor?.valueParameters?.size ?: 0)
|
||||
|
||||
private val ctorEnvironmentVarsParametersStart =
|
||||
private val ctorProvidedPropertiesParametersStart =
|
||||
ctorImplicitReceiversParametersStart + scriptDescriptor.implicitReceivers.size
|
||||
|
||||
fun getImplicitReceiverName(index: Int): String =
|
||||
scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters[ctorImplicitReceiversParametersStart + index].name.identifier
|
||||
|
||||
fun getImplicitReceiverType(index: Int): Type? {
|
||||
val receivers = script.kotlinScriptDefinition.implicitReceivers
|
||||
val kClass = receivers.getOrNull(index)?.classifier as? KClass<*>
|
||||
return kClass?.java?.classId?.let(AsmUtil::asmTypeByClassId)
|
||||
val receiverParam = scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters[ctorImplicitReceiversParametersStart + index]
|
||||
return state.typeMapper.mapType(receiverParam.type)
|
||||
}
|
||||
|
||||
fun getEnvironmentVarName(index: Int): String =
|
||||
scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters[ctorEnvironmentVarsParametersStart + index].name.identifier
|
||||
fun getProvidedPropertyName(index: Int): String =
|
||||
scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters[ctorProvidedPropertiesParametersStart + index].name.identifier
|
||||
|
||||
fun getEnvironmentVarType(index: Int): Type = typeMapper.mapType(scriptDescriptor.scriptEnvironmentProperties[index].type)
|
||||
fun getProvidedPropertyType(index: Int): Type = typeMapper.mapType(scriptDescriptor.scriptProvidedProperties[index].type)
|
||||
|
||||
fun getOuterReceiverExpression(prefix: StackValue?, thisOrOuterClass: ClassDescriptor): StackValue {
|
||||
if (thisOrOuterClass is ScriptEnvironmentDescriptor) {
|
||||
if (thisOrOuterClass is ScriptProvidedPropertiesDescriptor) {
|
||||
return prefix ?: StackValue.LOCAL_0
|
||||
}
|
||||
receiverDescriptors.forEachIndexed { index, outerReceiver ->
|
||||
@@ -113,10 +110,8 @@ class ScriptContext(
|
||||
|
||||
fun getScriptFieldName(scriptDescriptor: ScriptDescriptor): String {
|
||||
val index = earlierScripts.indexOf(scriptDescriptor)
|
||||
if (index < 0) {
|
||||
throw IllegalStateException("Unregistered script: $scriptDescriptor")
|
||||
}
|
||||
return "script$" + (index + 1)
|
||||
return if (index >= 0) "script$" + (index + 1)
|
||||
else "\$\$importedScript${scriptDescriptor.name.identifier}"
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
@@ -652,7 +652,8 @@ class CoroutineCodegenForNamedFunction private constructor(
|
||||
override fun generateKotlinMetadataAnnotation() {
|
||||
writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) { av ->
|
||||
val serializer = DescriptorSerializer.createForLambda(JvmSerializerExtension(v.serializationBindings, state))
|
||||
val functionProto = serializer.functionProto(createFreeFakeLambdaDescriptor(suspendFunctionJvmView)).build()
|
||||
val functionProto =
|
||||
serializer.functionProto(createFreeFakeLambdaDescriptor(suspendFunctionJvmView))?.build() ?: return@writeKotlinMetadata
|
||||
AsmUtil.writeAnnotationData(av, serializer, functionProto)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class KClassJavaObjectTypeProperty : IntrinsicPropertyGetter() {
|
||||
}
|
||||
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(lhs.type, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
|
||||
}
|
||||
iv.aconst(AsmUtil.boxType(codegen.asmType(lhs.type)))
|
||||
iv.aconst(AsmUtil.boxType(codegen.mapTypeAsDeclaration(lhs.type)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.psi.KtClassLiteralExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
@@ -32,21 +33,28 @@ class KClassJavaPrimitiveTypeProperty : IntrinsicPropertyGetter() {
|
||||
val receiverType = codegen.bindingContext.getType(receiverExpression) ?: return null
|
||||
if (!KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType(receiverType)) return null
|
||||
}
|
||||
|
||||
val lhsType = codegen.asmType(lhs.type)
|
||||
return StackValue.operation(returnType) { iv ->
|
||||
when {
|
||||
lhs is DoubleColonLHS.Expression && !lhs.isObjectQualifier -> {
|
||||
codegen.gen(receiverExpression).put(lhsType, iv)
|
||||
AsmUtil.pop(iv, lhsType)
|
||||
if (lhs.type.isInlineClassType())
|
||||
iv.aconst(null)
|
||||
else
|
||||
iv.getstatic(AsmUtil.boxType(lhsType).internalName, "TYPE", "Ljava/lang/Class;")
|
||||
}
|
||||
|
||||
!lhs.type.isInlineClassType() && isPrimitiveOrWrapper(lhsType) -> {
|
||||
iv.getstatic(AsmUtil.boxType(lhsType).internalName, "TYPE", "Ljava/lang/Class;")
|
||||
}
|
||||
AsmUtil.isPrimitive(lhsType) ||
|
||||
AsmUtil.unboxPrimitiveTypeOrNull(lhsType) != null ||
|
||||
AsmTypes.VOID_WRAPPER_TYPE == lhsType -> {
|
||||
iv.getstatic(AsmUtil.boxType(lhsType).internalName, "TYPE", "Ljava/lang/Class;")
|
||||
}
|
||||
|
||||
else -> iv.aconst(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isPrimitiveOrWrapper(lhsType: Type) =
|
||||
AsmUtil.isPrimitive(lhsType) || AsmUtil.unboxPrimitiveTypeOrNull(lhsType) != null || AsmTypes.VOID_WRAPPER_TYPE == lhsType
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPrivateApi
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
@@ -47,6 +48,21 @@ class JvmSerializerExtension(private val bindings: JvmSerializationBindings, sta
|
||||
override val metadataVersion = state.metadataVersion
|
||||
|
||||
override fun shouldUseTypeTable(): Boolean = useTypeTable
|
||||
override fun shouldSerializeFunction(descriptor: FunctionDescriptor): Boolean {
|
||||
return classBuilderMode != ClassBuilderMode.ABI || descriptor.visibility != Visibilities.PRIVATE
|
||||
}
|
||||
|
||||
override fun shouldSerializeProperty(descriptor: PropertyDescriptor): Boolean {
|
||||
return classBuilderMode != ClassBuilderMode.ABI || descriptor.visibility != Visibilities.PRIVATE
|
||||
}
|
||||
|
||||
override fun shouldSerializeTypeAlias(descriptor: TypeAliasDescriptor): Boolean {
|
||||
return classBuilderMode != ClassBuilderMode.ABI || descriptor.visibility != Visibilities.PRIVATE
|
||||
}
|
||||
|
||||
override fun shouldSerializeNestedClass(descriptor: ClassDescriptor): Boolean {
|
||||
return classBuilderMode != ClassBuilderMode.ABI || !descriptor.isEffectivelyPrivateApi
|
||||
}
|
||||
|
||||
override fun serializeClass(
|
||||
descriptor: ClassDescriptor,
|
||||
@@ -103,7 +119,7 @@ class JvmSerializerExtension(private val bindings: JvmSerializationBindings, sta
|
||||
for (localVariable in localVariables) {
|
||||
val propertyDescriptor = createFreeFakeLocalPropertyDescriptor(localVariable)
|
||||
val serializer = DescriptorSerializer.createForLambda(this)
|
||||
proto.addExtension(extension, serializer.propertyProto(propertyDescriptor).build())
|
||||
proto.addExtension(extension, serializer.propertyProto(propertyDescriptor)?.build() ?: continue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import gnu.trove.THashSet
|
||||
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.JavaClassFinder
|
||||
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
|
||||
@@ -81,7 +82,10 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
|
||||
private val signatureParsingComponent = BinaryClassSignatureParser()
|
||||
|
||||
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
|
||||
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? = findClass(JavaClassFinder.Request(classId), searchScope)
|
||||
|
||||
override fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass? {
|
||||
val (classId, classFileContentFromRequest, outerClassFromRequest) = request
|
||||
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
|
||||
|
||||
if (useFastClassFilesReading && virtualFile.extension == "class") {
|
||||
@@ -92,13 +96,20 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
// This is a true assumption by now since there are two search scopes in compiler: one for sources and another one for binary
|
||||
// When it become wrong because we introduce the modules into CLI, it's worth to consider
|
||||
// having different KotlinCliJavaFileManagerImpl's for different modules
|
||||
val classContent = virtualFile.contentsToByteArray()
|
||||
if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null
|
||||
|
||||
classId.outerClassId?.let { outerClassId ->
|
||||
val outerClass = findClass(outerClassId, searchScope)
|
||||
return@getOrPut outerClass?.findInnerClass(classId.shortClassName)
|
||||
val outerClass = outerClassFromRequest ?: findClass(outerClassId, searchScope)
|
||||
|
||||
return if (outerClass is BinaryJavaClass)
|
||||
outerClass.findInnerClass(classId.shortClassName, classFileContentFromRequest)
|
||||
else
|
||||
outerClass?.findInnerClass(classId.shortClassName)
|
||||
}
|
||||
|
||||
// Here, we assume the class is top-level
|
||||
val classContent = classFileContentFromRequest ?: virtualFile.contentsToByteArray()
|
||||
if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null
|
||||
|
||||
val resolver = ClassifierResolutionContext { findClass(it, allScope) }
|
||||
|
||||
BinaryJavaClass(
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.InferredAnnotationsManager
|
||||
import com.intellij.codeInsight.runner.JavaMainMethodProvider
|
||||
import com.intellij.core.*
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.lang.MetaLanguage
|
||||
import com.intellij.lang.java.JavaParserDefinition
|
||||
import com.intellij.openapi.Disposable
|
||||
@@ -69,6 +68,7 @@ import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PRO
|
||||
import org.jetbrains.kotlin.cli.common.config.ContentRoot
|
||||
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
|
||||
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
|
||||
@@ -241,16 +241,13 @@ class KotlinCoreEnvironment private constructor(
|
||||
}
|
||||
|
||||
sourceFiles += createKtFiles(project)
|
||||
sourceFiles.sortBy { it.virtualFile.path }
|
||||
|
||||
if (scriptDefinitionProvider != null) {
|
||||
ScriptDependenciesProvider.getInstance(project).let { importsProvider ->
|
||||
configuration.addJvmClasspathRoots(
|
||||
sourceFiles.mapNotNull(importsProvider::getScriptDependencies)
|
||||
.flatMap { it.classpath }
|
||||
.distinctBy { it.absolutePath })
|
||||
}
|
||||
val (classpath, newSources, _) = collectScriptsCompilationDependencies(configuration, project, sourceFiles)
|
||||
configuration.addJvmClasspathRoots(classpath)
|
||||
sourceFiles += newSources
|
||||
}
|
||||
sourceFiles.sortBy { it.virtualFile.path }
|
||||
|
||||
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
|
||||
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
|
||||
@@ -427,58 +424,10 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
fun getSourceFiles(): List<KtFile> = sourceFiles
|
||||
|
||||
private fun createKtFiles(project: Project): List<KtFile> {
|
||||
val sourceRoots = getSourceRootsCheckingForDuplicates()
|
||||
private fun createKtFiles(project: Project): List<KtFile> =
|
||||
createSourceFilesFromSourceRoots(configuration, project, getSourceRootsCheckingForDuplicates())
|
||||
|
||||
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
||||
val psiManager = PsiManager.getInstance(project)
|
||||
|
||||
val processedFiles = hashSetOf<VirtualFile>()
|
||||
val result = mutableListOf<KtFile>()
|
||||
|
||||
val virtualFileCreator = PreprocessedFileCreator(project)
|
||||
|
||||
for ((sourceRootPath, isCommon) in sourceRoots) {
|
||||
val vFile = localFileSystem.findFileByPath(sourceRootPath)
|
||||
if (vFile == null) {
|
||||
val message = "Source file or directory not found: $sourceRootPath"
|
||||
|
||||
val buildFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE)
|
||||
if (buildFilePath != null && Logger.isInitialized()) {
|
||||
LOG.warn("$message\n\nbuild file path: $buildFilePath\ncontent:\n${buildFilePath.readText()}")
|
||||
}
|
||||
|
||||
report(ERROR, message)
|
||||
continue
|
||||
}
|
||||
|
||||
if (!vFile.isDirectory && vFile.fileType != KotlinFileType.INSTANCE) {
|
||||
report(ERROR, "Source entry is not a Kotlin file: $sourceRootPath")
|
||||
continue
|
||||
}
|
||||
|
||||
for (file in File(sourceRootPath).walkTopDown()) {
|
||||
if (!file.isFile) continue
|
||||
|
||||
val virtualFile = localFileSystem.findFileByPath(file.absolutePath)?.let(virtualFileCreator::create)
|
||||
if (virtualFile != null && processedFiles.add(virtualFile)) {
|
||||
val psiFile = psiManager.findFile(virtualFile)
|
||||
if (psiFile is KtFile) {
|
||||
result.add(psiFile)
|
||||
if (isCommon) {
|
||||
psiFile.isCommonSource = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun report(severity: CompilerMessageSeverity, message: String) {
|
||||
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(severity, message)
|
||||
}
|
||||
internal fun report(severity: CompilerMessageSeverity, message: String) = report(configuration, severity, message)
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java)
|
||||
@@ -531,6 +480,67 @@ class KotlinCoreEnvironment private constructor(
|
||||
// used in the daemon for jar cache cleanup
|
||||
val applicationEnvironment: JavaCoreApplicationEnvironment? get() = ourApplicationEnvironment
|
||||
|
||||
internal fun report(
|
||||
configuration: CompilerConfiguration,
|
||||
severity: CompilerMessageSeverity,
|
||||
message: String,
|
||||
location: CompilerMessageLocation? = null
|
||||
) {
|
||||
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(severity, message, location)
|
||||
}
|
||||
|
||||
internal fun createSourceFilesFromSourceRoots(
|
||||
configuration: CompilerConfiguration,
|
||||
project: Project,
|
||||
sourceRoots: List<KotlinSourceRoot>,
|
||||
reportLocation: CompilerMessageLocation? = null
|
||||
): MutableList<KtFile> {
|
||||
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
||||
val psiManager = PsiManager.getInstance(project)
|
||||
|
||||
val processedFiles = hashSetOf<VirtualFile>()
|
||||
val result = mutableListOf<KtFile>()
|
||||
|
||||
val virtualFileCreator = PreprocessedFileCreator(project)
|
||||
|
||||
for ((sourceRootPath, isCommon) in sourceRoots) {
|
||||
val vFile = localFileSystem.findFileByPath(sourceRootPath)
|
||||
if (vFile == null) {
|
||||
val message = "Source file or directory not found: $sourceRootPath"
|
||||
|
||||
val buildFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE)
|
||||
if (buildFilePath != null && Logger.isInitialized()) {
|
||||
KotlinCoreEnvironment.LOG.warn("$message\n\nbuild file path: $buildFilePath\ncontent:\n${buildFilePath.readText()}")
|
||||
}
|
||||
|
||||
report(configuration, ERROR, message, reportLocation)
|
||||
continue
|
||||
}
|
||||
|
||||
if (!vFile.isDirectory && vFile.fileType != KotlinFileType.INSTANCE) {
|
||||
report(configuration, ERROR, "Source entry is not a Kotlin file: $sourceRootPath", reportLocation)
|
||||
continue
|
||||
}
|
||||
|
||||
for (file in File(sourceRootPath).walkTopDown()) {
|
||||
if (!file.isFile) continue
|
||||
|
||||
val virtualFile = localFileSystem.findFileByPath(file.absolutePath)?.let(virtualFileCreator::create)
|
||||
if (virtualFile != null && processedFiles.add(virtualFile)) {
|
||||
val psiFile = psiManager.findFile(virtualFile)
|
||||
if (psiFile is KtFile) {
|
||||
result.add(psiFile)
|
||||
if (isCommon) {
|
||||
psiFile.isCommonSource = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun getOrCreateApplicationEnvironmentForProduction(configuration: CompilerConfiguration): JavaCoreApplicationEnvironment {
|
||||
synchronized(APPLICATION_LOCK) {
|
||||
if (ourApplicationEnvironment != null)
|
||||
@@ -701,3 +711,4 @@ class KotlinCoreEnvironment private constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ object KotlinToJVMBytecodeCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun compileAndExecuteScript(environment: KotlinCoreEnvironment, scriptArgs: List<String>): ExitCode {
|
||||
fun compileAndExecuteScript(environment: KotlinCoreEnvironment, scriptArgs: List<String>): ExitCode {
|
||||
val scriptClass = compileScript(environment) ?: return ExitCode.COMPILATION_ERROR
|
||||
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.jvm.compiler
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
||||
import java.io.File
|
||||
|
||||
data class ScriptsCompilationDependencies(
|
||||
val classpath: List<File>,
|
||||
val sources: List<KtFile>,
|
||||
val sourceDependencies: List<SourceDependencies>
|
||||
) {
|
||||
data class SourceDependencies(
|
||||
val scriptFile: KtFile,
|
||||
val sourceDependencies: List<KtFile>
|
||||
)
|
||||
}
|
||||
|
||||
// recursively collect dependencies from initial and imported scripts
|
||||
fun collectScriptsCompilationDependencies(
|
||||
configuration: CompilerConfiguration,
|
||||
project: Project,
|
||||
initialSources: Iterable<KtFile>
|
||||
): ScriptsCompilationDependencies {
|
||||
val collectedClassPath = ArrayList<File>()
|
||||
val collectedSources = ArrayList<KtFile>()
|
||||
val collectedSourceDependencies = ArrayList<ScriptsCompilationDependencies.SourceDependencies>()
|
||||
var remainingSources = initialSources
|
||||
val knownSourcePaths = initialSources.mapNotNullTo(HashSet()) { it.virtualFile?.path }
|
||||
val importsProvider = ScriptDependenciesProvider.getInstance(project)
|
||||
while (true) {
|
||||
val newRemainingSources = ArrayList<KtFile>()
|
||||
for (source in remainingSources) {
|
||||
val dependencies = importsProvider.getScriptDependencies(source)
|
||||
if (dependencies != null) {
|
||||
collectedClassPath.addAll(dependencies.classpath)
|
||||
|
||||
val sourceDependenciesRoots = dependencies.scripts.map {
|
||||
KotlinSourceRoot(it.path, false)
|
||||
}
|
||||
val sourceDependencies =
|
||||
KotlinCoreEnvironment.createSourceFilesFromSourceRoots(
|
||||
configuration, project, sourceDependenciesRoots,
|
||||
// TODO: consider receiving and using precise location from the resolver in the future
|
||||
source.virtualFile?.path?.let { CompilerMessageLocation.create(it) }
|
||||
)
|
||||
if (sourceDependencies.isNotEmpty()) {
|
||||
collectedSourceDependencies.add(ScriptsCompilationDependencies.SourceDependencies(source, sourceDependencies))
|
||||
|
||||
val newSources = sourceDependencies.filterNot { knownSourcePaths.contains(it.virtualFile.path) }
|
||||
for (newSource in newSources) {
|
||||
collectedSources.add(newSource)
|
||||
newRemainingSources.add(newSource)
|
||||
knownSourcePaths.add(newSource.virtualFile.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newRemainingSources.isEmpty()) break
|
||||
else {
|
||||
remainingSources = newRemainingSources
|
||||
}
|
||||
}
|
||||
return ScriptsCompilationDependencies(
|
||||
collectedClassPath.distinctBy { it.absolutePath },
|
||||
collectedSources,
|
||||
collectedSourceDependencies
|
||||
)
|
||||
}
|
||||
@@ -91,6 +91,7 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
val analysisHandlerExtensions = AnalysisHandlerExtension.getInstances(project)
|
||||
|
||||
fun invokeExtensionsOnAnalysisComplete(): AnalysisResult? {
|
||||
container.get<JavaClassesTracker>().onCompletedAnalysis(module)
|
||||
for (extension in analysisHandlerExtensions) {
|
||||
val result = extension.analysisCompleted(project, module, trace, files)
|
||||
if (result != null) return result
|
||||
@@ -108,7 +109,6 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
}
|
||||
|
||||
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||
container.get<JavaClassesTracker>().onCompletedAnalysis(module)
|
||||
|
||||
invokeExtensionsOnAnalysisComplete()?.let { return it }
|
||||
|
||||
|
||||
@@ -11,7 +11,10 @@ import java.lang.Character.isJavaIdentifierPart
|
||||
import java.lang.Character.isJavaIdentifierStart
|
||||
import java.lang.IllegalArgumentException
|
||||
import java.lang.RuntimeException
|
||||
import java.lang.UnsupportedOperationException
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.file.FileSystemNotFoundException
|
||||
import java.nio.file.Paths
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
/**
|
||||
@@ -32,9 +35,13 @@ object ServiceLoaderLite {
|
||||
*/
|
||||
fun <Service> loadImplementations(service: Class<out Service>, classLoader: URLClassLoader): List<Service> {
|
||||
val files = classLoader.urLs.map { url ->
|
||||
if (url.protocol.toLowerCase() != "file") throw IllegalArgumentException("Only local files are supported, got $url")
|
||||
val path = url.path.takeIf { it.isNotEmpty() } ?: throw IllegalArgumentException("Path is empty for $url")
|
||||
File(path)
|
||||
try {
|
||||
Paths.get(url.toURI()).toFile()
|
||||
} catch (e: FileSystemNotFoundException) {
|
||||
throw IllegalArgumentException("Only local URLs are supported, got ${url.protocol}")
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
throw IllegalArgumentException("Only local URLs are supported, got ${url.protocol}")
|
||||
}
|
||||
}
|
||||
|
||||
val implementations = mutableListOf<Service>()
|
||||
|
||||
@@ -200,6 +200,7 @@ messages/**)
|
||||
-keep class org.jetbrains.org.objectweb.asm.tree.FieldNode { *; }
|
||||
-keep class org.jetbrains.org.objectweb.asm.tree.ParameterNode { *; }
|
||||
-keep class org.jetbrains.org.objectweb.asm.tree.TypeAnnotationNode { *; }
|
||||
-keep class org.jetbrains.org.objectweb.asm.tree.InsnList { *; }
|
||||
|
||||
-keep class org.jetbrains.org.objectweb.asm.signature.SignatureReader { *; }
|
||||
-keep class org.jetbrains.org.objectweb.asm.signature.SignatureVisitor { *; }
|
||||
@@ -236,6 +237,9 @@ messages/**)
|
||||
|
||||
# for kapt
|
||||
-keep class com.intellij.openapi.project.Project { *; }
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
}
|
||||
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
@@ -245,3 +249,6 @@ messages/**)
|
||||
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
|
||||
|
||||
-keep class net.jpountz.lz4.* { *; }
|
||||
|
||||
# used in LazyScriptDescriptor
|
||||
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }
|
||||
|
||||
@@ -219,6 +219,9 @@ messages/**)
|
||||
|
||||
# for kapt
|
||||
-keep class com.intellij.openapi.project.Project { *; }
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
}
|
||||
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
@@ -228,3 +231,6 @@ messages/**)
|
||||
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
|
||||
|
||||
-keep class net.jpountz.lz4.* { *; }
|
||||
|
||||
# used in LazyScriptDescriptor
|
||||
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }
|
||||
|
||||
@@ -237,6 +237,9 @@ messages/**)
|
||||
|
||||
# for kapt
|
||||
-keep class com.intellij.openapi.project.Project { *; }
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
}
|
||||
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
@@ -246,3 +249,6 @@ messages/**)
|
||||
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
|
||||
|
||||
-keep class net.jpountz.lz4.* { *; }
|
||||
|
||||
# used in LazyScriptDescriptor
|
||||
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }
|
||||
|
||||
@@ -220,6 +220,9 @@ messages/**)
|
||||
|
||||
# for kapt
|
||||
-keep class com.intellij.openapi.project.Project { *; }
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
}
|
||||
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
@@ -227,3 +230,6 @@ messages/**)
|
||||
|
||||
# remove when KT-18563 would be fixed
|
||||
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
|
||||
|
||||
# used in LazyScriptDescriptor
|
||||
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }
|
||||
|
||||
@@ -237,6 +237,9 @@ messages/**)
|
||||
|
||||
# for kapt
|
||||
-keep class com.intellij.openapi.project.Project { *; }
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
}
|
||||
|
||||
-keepclassmembers class com.intellij.util.PathUtil {
|
||||
public static java.lang.String getJarPathForClass(java.lang.Class);
|
||||
@@ -246,3 +249,6 @@ messages/**)
|
||||
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
|
||||
|
||||
-keep class net.jpountz.lz4.* { *; }
|
||||
|
||||
# used in LazyScriptDescriptor
|
||||
-keep class org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt { *; }
|
||||
|
||||
@@ -102,7 +102,7 @@ class StorageComponentContainer(private val id: String, parent: StorageComponent
|
||||
override fun <T> create(request: Class<T>): T {
|
||||
val constructorBinding = request.bindToConstructor(unknownContext)
|
||||
val args = constructorBinding.argumentDescriptors.map { it.getValue() }.toTypedArray()
|
||||
return constructorBinding.constructor.newInstance(*args) as T
|
||||
return runWithUnwrappingInvocationException { constructorBinding.constructor.newInstance(*args) as T }
|
||||
}
|
||||
|
||||
override fun toString() = "Container $id"
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Member
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Type
|
||||
import java.util.ArrayList
|
||||
import java.util.*
|
||||
|
||||
interface ValueResolver {
|
||||
fun resolve(request: Type, context: ValueResolveContext): ValueDescriptor?
|
||||
@@ -45,7 +45,7 @@ class ConstructorBinding(val constructor: Constructor<*>, val argumentDescriptor
|
||||
class MethodBinding(val method: Method, private val argumentDescriptors: List<ValueDescriptor>) {
|
||||
fun invoke(instance: Any) {
|
||||
val arguments = computeArguments(argumentDescriptors).toTypedArray()
|
||||
method.invoke(instance, *arguments)
|
||||
runWithUnwrappingInvocationException { method.invoke(instance, *arguments) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.container
|
||||
|
||||
import java.io.Closeable
|
||||
import java.lang.reflect.Type
|
||||
import java.util.ArrayList
|
||||
import java.util.*
|
||||
|
||||
enum class ComponentState {
|
||||
Null,
|
||||
@@ -131,7 +131,7 @@ open class SingletonTypeComponentDescriptor(container: ComponentContainer, val k
|
||||
val constructor = binding.constructor
|
||||
val arguments = computeArguments(binding.argumentDescriptors)
|
||||
|
||||
val instance = constructor.newInstance(*arguments.toTypedArray())!!
|
||||
val instance = runWithUnwrappingInvocationException { constructor.newInstance(*arguments.toTypedArray())!! }
|
||||
state = ComponentState.Initialized
|
||||
return instance
|
||||
}
|
||||
@@ -154,4 +154,4 @@ class DefaultSingletonTypeComponentDescriptor(container: ComponentContainer, kla
|
||||
override fun toString(): String {
|
||||
return "Default: ${klass.simpleName}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.container
|
||||
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
|
||||
inline fun <T> runWithUnwrappingInvocationException(block: () -> T) =
|
||||
try {
|
||||
block()
|
||||
} catch (e: InvocationTargetException) {
|
||||
throw e.targetException ?: e
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.fir.java.symbols.JavaClassSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
||||
@@ -38,7 +39,7 @@ class JavaSymbolProvider(val project: Project) : FirSymbolProvider {
|
||||
override fun getSymbolByFqName(classId: ClassId): ConeSymbol? {
|
||||
return classCache.lookupCacheOrCalculate(classId) {
|
||||
val facade = KotlinJavaPsiFacade.getInstance(project)
|
||||
val foundClass = facade.findClass(classId, allScope)
|
||||
val foundClass = facade.findClass(JavaClassFinder.Request(classId), allScope)
|
||||
foundClass?.let { javaClass -> JavaClassSymbol(javaClass) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.load.java
|
||||
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaPackageImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
||||
@@ -33,10 +32,10 @@ class JavaClassFinderImpl : AbstractJavaClassFinder() {
|
||||
super.initialize(trace, codeAnalyzer)
|
||||
}
|
||||
|
||||
override fun findClass(classId: ClassId): JavaClass? = javaFacade.findClass(classId, javaSearchScope)
|
||||
override fun findClass(request: JavaClassFinder.Request): JavaClass? = javaFacade.findClass(request, javaSearchScope)
|
||||
|
||||
override fun findPackage(fqName: FqName) = javaFacade.findPackage(fqName.asString(), javaSearchScope)?.let { JavaPackageImpl(it, javaSearchScope) }
|
||||
|
||||
override fun knownClassNamesInPackage(packageFqName: FqName): Set<String>? = javaFacade.knownClassNamesInPackage(packageFqName)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,13 +31,13 @@ import java.text.CharacterIterator
|
||||
import java.text.StringCharacterIterator
|
||||
|
||||
class BinaryJavaClass(
|
||||
override val virtualFile: VirtualFile,
|
||||
override val fqName: FqName,
|
||||
internal val context: ClassifierResolutionContext,
|
||||
private val signatureParser: BinaryClassSignatureParser,
|
||||
override var access: Int = 0,
|
||||
override val outerClass: JavaClass?,
|
||||
classContent: ByteArray? = null
|
||||
override val virtualFile: VirtualFile,
|
||||
override val fqName: FqName,
|
||||
internal val context: ClassifierResolutionContext,
|
||||
private val signatureParser: BinaryClassSignatureParser,
|
||||
override var access: Int = 0,
|
||||
override val outerClass: JavaClass?,
|
||||
classContent: ByteArray? = null
|
||||
) : ClassVisitor(ASM_API_VERSION_FOR_CLASS_READING), VirtualFileBoundJavaClass, BinaryJavaModifierListOwner, MapBasedJavaAnnotationOwner {
|
||||
private lateinit var myInternalName: String
|
||||
|
||||
@@ -74,8 +74,8 @@ class BinaryJavaClass(
|
||||
|
||||
init {
|
||||
ClassReader(classContent ?: virtualFile.contentsToByteArray()).accept(
|
||||
this,
|
||||
ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES
|
||||
this,
|
||||
ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES
|
||||
)
|
||||
}
|
||||
|
||||
@@ -115,20 +115,19 @@ class BinaryJavaClass(
|
||||
}
|
||||
|
||||
override fun visit(
|
||||
version: Int,
|
||||
access: Int,
|
||||
name: String,
|
||||
signature: String?,
|
||||
superName: String?,
|
||||
interfaces: Array<out String>?
|
||||
version: Int,
|
||||
access: Int,
|
||||
name: String,
|
||||
signature: String?,
|
||||
superName: String?,
|
||||
interfaces: Array<out String>?
|
||||
) {
|
||||
this.access = this.access or access
|
||||
this.myInternalName = name
|
||||
|
||||
if (signature != null) {
|
||||
parseClassSignature(signature)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.typeParameters = emptyList()
|
||||
this.supertypes = mutableListOf<JavaClassifierType>().apply {
|
||||
addIfNotNull(superName?.convertInternalNameToClassifierType())
|
||||
@@ -142,9 +141,9 @@ class BinaryJavaClass(
|
||||
private fun parseClassSignature(signature: String) {
|
||||
val iterator = StringCharacterIterator(signature)
|
||||
this.typeParameters =
|
||||
signatureParser
|
||||
.parseTypeParametersDeclaration(iterator, context)
|
||||
.also(context::addTypeParameters)
|
||||
signatureParser
|
||||
.parseTypeParametersDeclaration(iterator, context)
|
||||
.also(context::addTypeParameters)
|
||||
|
||||
val supertypes = ContainerUtil.newSmartList<JavaClassifierType>()
|
||||
supertypes.addIfNotNull(signatureParser.parseClassifierRefSignature(iterator, context))
|
||||
@@ -155,7 +154,7 @@ class BinaryJavaClass(
|
||||
}
|
||||
|
||||
private fun String.convertInternalNameToClassifierType(): JavaClassifierType =
|
||||
PlainJavaClassifierType({ context.resolveByInternalName(this) }, emptyList())
|
||||
PlainJavaClassifierType({ context.resolveByInternalName(this) }, emptyList())
|
||||
|
||||
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
||||
if (access.isSet(Opcodes.ACC_SYNTHETIC)) return null
|
||||
@@ -169,13 +168,13 @@ class BinaryJavaClass(
|
||||
|
||||
object : FieldVisitor(ASM_API_VERSION_FOR_CLASS_READING) {
|
||||
override fun visitAnnotation(desc: String, visible: Boolean) =
|
||||
BinaryJavaAnnotation.addAnnotation(this@run.annotations, desc, context, signatureParser)
|
||||
BinaryJavaAnnotation.addAnnotation(this@run.annotations, desc, context, signatureParser)
|
||||
|
||||
override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String, visible: Boolean) =
|
||||
if (typePath == null)
|
||||
BinaryJavaAnnotation.addTypeAnnotation(type, desc, context, signatureParser)
|
||||
else
|
||||
null
|
||||
if (typePath == null)
|
||||
BinaryJavaAnnotation.addTypeAnnotation(type, desc, context, signatureParser)
|
||||
else
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +186,7 @@ class BinaryJavaClass(
|
||||
if (fieldType !is JavaPrimitiveType || fieldType.type == null || value !is Int) return value
|
||||
|
||||
return when (fieldType.type) {
|
||||
PrimitiveType.BOOLEAN -> {
|
||||
PrimitiveType.BOOLEAN -> {
|
||||
when (value) {
|
||||
0 -> false
|
||||
1 -> true
|
||||
@@ -200,13 +199,18 @@ class BinaryJavaClass(
|
||||
}
|
||||
|
||||
override fun visitAnnotation(desc: String, visible: Boolean) =
|
||||
BinaryJavaAnnotation.addAnnotation(annotations, desc, context, signatureParser)
|
||||
BinaryJavaAnnotation.addAnnotation(annotations, desc, context, signatureParser)
|
||||
|
||||
override fun findInnerClass(name: Name): JavaClass? {
|
||||
override fun findInnerClass(name: Name): JavaClass? = findInnerClass(name, classFileContent = null)
|
||||
|
||||
fun findInnerClass(name: Name, classFileContent: ByteArray?): JavaClass? {
|
||||
val access = ownInnerClassNameToAccess[name] ?: return null
|
||||
|
||||
return virtualFile.parent.findChild("${virtualFile.nameWithoutExtension}$$name.class")?.let {
|
||||
BinaryJavaClass(it, fqName.child(name), context.copyForMember(), signatureParser, access, this)
|
||||
BinaryJavaClass(
|
||||
it, fqName.child(name), context.copyForMember(), signatureParser, access, this,
|
||||
classFileContent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.load.java.structure.JavaModifierListOwner
|
||||
import org.jetbrains.kotlin.load.java.structure.MapBasedJavaAnnotationOwner
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
internal val ASM_API_VERSION_FOR_CLASS_READING = Opcodes.ASM5
|
||||
internal const val ASM_API_VERSION_FOR_CLASS_READING = Opcodes.API_VERSION
|
||||
|
||||
internal interface BinaryJavaModifierListOwner : JavaModifierListOwner, MapBasedJavaAnnotationOwner {
|
||||
val access: Int
|
||||
|
||||
@@ -85,7 +85,7 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
|
||||
|
||||
// TODO public to be accessible in companion object of subclass, workaround for KT-3974
|
||||
@Nullable
|
||||
public static <T extends FileBasedKotlinClass> T create(
|
||||
public static <T> T create(
|
||||
@NotNull byte[] fileContents,
|
||||
@NotNull Function4<ClassId, Integer, KotlinClassHeader, InnerClassesInfo, T> factory
|
||||
) {
|
||||
|
||||
@@ -28,14 +28,17 @@ class KotlinBinaryClassCache : Disposable {
|
||||
private class RequestCache {
|
||||
internal var virtualFile: VirtualFile? = null
|
||||
internal var modificationStamp: Long = 0
|
||||
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
|
||||
internal var result: KotlinClassFinder.Result? = null
|
||||
|
||||
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
|
||||
fun cache(
|
||||
file: VirtualFile,
|
||||
result: KotlinClassFinder.Result?
|
||||
): KotlinClassFinder.Result? {
|
||||
virtualFile = file
|
||||
virtualFileKotlinClass = aClass
|
||||
this.result = result
|
||||
modificationStamp = file.modificationStamp
|
||||
|
||||
return aClass
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +56,9 @@ class KotlinBinaryClassCache : Disposable {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
|
||||
fun getKotlinBinaryClassOrClassFileContent(
|
||||
file: VirtualFile, fileContent: ByteArray? = null
|
||||
): KotlinClassFinder.Result? {
|
||||
if (file.fileType !== JavaClassFileType.INSTANCE) return null
|
||||
|
||||
if (file.name == PsiJavaModule.MODULE_INFO_CLS_FILE) return null
|
||||
@@ -62,7 +67,7 @@ class KotlinBinaryClassCache : Disposable {
|
||||
val requestCache = service.cache.get()
|
||||
|
||||
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
|
||||
return requestCache.virtualFileKotlinClass
|
||||
return requestCache.result
|
||||
}
|
||||
|
||||
val aClass = ApplicationManager.getApplication().runReadAction(Computable {
|
||||
|
||||
@@ -27,14 +27,17 @@ class KotlinBinaryClassCache : Disposable {
|
||||
private class RequestCache {
|
||||
internal var virtualFile: VirtualFile? = null
|
||||
internal var modificationStamp: Long = 0
|
||||
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
|
||||
internal var result: KotlinClassFinder.Result? = null
|
||||
|
||||
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
|
||||
fun cache(
|
||||
file: VirtualFile,
|
||||
result: KotlinClassFinder.Result?
|
||||
): KotlinClassFinder.Result? {
|
||||
virtualFile = file
|
||||
virtualFileKotlinClass = aClass
|
||||
this.result = result
|
||||
modificationStamp = file.modificationStamp
|
||||
|
||||
return aClass
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,14 +55,16 @@ class KotlinBinaryClassCache : Disposable {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
|
||||
fun getKotlinBinaryClassOrClassFileContent(
|
||||
file: VirtualFile, fileContent: ByteArray? = null
|
||||
): KotlinClassFinder.Result? {
|
||||
if (file.fileType !== JavaClassFileType.INSTANCE) return null
|
||||
|
||||
val service = ServiceManager.getService(KotlinBinaryClassCache::class.java)
|
||||
val requestCache = service.cache.get()
|
||||
|
||||
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
|
||||
return requestCache.virtualFileKotlinClass
|
||||
return requestCache.result
|
||||
}
|
||||
|
||||
val aClass = ApplicationManager.getApplication().runReadAction(Computable {
|
||||
|
||||
@@ -27,14 +27,17 @@ class KotlinBinaryClassCache : Disposable {
|
||||
private class RequestCache {
|
||||
internal var virtualFile: VirtualFile? = null
|
||||
internal var modificationStamp: Long = 0
|
||||
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
|
||||
internal var result: KotlinClassFinder.Result? = null
|
||||
|
||||
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
|
||||
fun cache(
|
||||
file: VirtualFile,
|
||||
result: KotlinClassFinder.Result?
|
||||
): KotlinClassFinder.Result? {
|
||||
virtualFile = file
|
||||
virtualFileKotlinClass = aClass
|
||||
this.result = result
|
||||
modificationStamp = file.modificationStamp
|
||||
|
||||
return aClass
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,14 +55,16 @@ class KotlinBinaryClassCache : Disposable {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
|
||||
fun getKotlinBinaryClassOrClassFileContent(
|
||||
file: VirtualFile, fileContent: ByteArray? = null
|
||||
): KotlinClassFinder.Result? {
|
||||
if (file.fileType !== JavaClassFileType.INSTANCE) return null
|
||||
|
||||
val service = ServiceManager.getService(KotlinBinaryClassCache::class.java)
|
||||
val requestCache = service.cache.get()
|
||||
|
||||
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
|
||||
return requestCache.virtualFileKotlinClass
|
||||
return requestCache.result
|
||||
}
|
||||
|
||||
val aClass = ApplicationManager.getApplication().runReadAction(Computable {
|
||||
|
||||
@@ -27,12 +27,12 @@ import org.jetbrains.kotlin.utils.sure
|
||||
abstract class VirtualFileFinder : KotlinClassFinder {
|
||||
abstract fun findVirtualFileWithHeader(classId: ClassId): VirtualFile?
|
||||
|
||||
override fun findKotlinClass(classId: ClassId): KotlinJvmBinaryClass? {
|
||||
override fun findKotlinClassOrContent(classId: ClassId): KotlinClassFinder.Result? {
|
||||
val file = findVirtualFileWithHeader(classId) ?: return null
|
||||
return KotlinBinaryClassCache.getKotlinBinaryClass(file)
|
||||
return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file)
|
||||
}
|
||||
|
||||
override fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? {
|
||||
override fun findKotlinClassOrContent(javaClass: JavaClass): KotlinClassFinder.Result? {
|
||||
var file = (javaClass as? VirtualFileBoundJavaClass)?.virtualFile ?: return null
|
||||
|
||||
if (javaClass.outerClass != null) {
|
||||
@@ -41,7 +41,7 @@ abstract class VirtualFileFinder : KotlinClassFinder {
|
||||
file = file.parent!!.findChild(classFileName(javaClass) + ".class").sure { "Virtual file not found for $javaClass" }
|
||||
}
|
||||
|
||||
return KotlinBinaryClassCache.getKotlinBinaryClass(file)
|
||||
return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file)
|
||||
}
|
||||
|
||||
private fun classFileName(jClass: JavaClass): String {
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.kotlin
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder.Result.KotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||
@@ -56,17 +57,19 @@ class VirtualFileKotlinClass private constructor(
|
||||
private val perfCounter = PerformanceCounter.create("Binary class from Kotlin file")
|
||||
|
||||
@Deprecated("Use KotlinBinaryClassCache")
|
||||
fun create(file: VirtualFile, fileContent: ByteArray?): VirtualFileKotlinClass? {
|
||||
fun create(file: VirtualFile, fileContent: ByteArray?): KotlinClassFinder.Result? {
|
||||
return perfCounter.time {
|
||||
assert(file.fileType == JavaClassFileType.INSTANCE) { "Trying to read binary data from a non-class file $file" }
|
||||
|
||||
try {
|
||||
val byteContent = fileContent ?: file.contentsToByteArray(false)
|
||||
if (!byteContent.isEmpty()) {
|
||||
return@time FileBasedKotlinClass.create(byteContent) {
|
||||
name, classVersion, header, innerClasses ->
|
||||
val kotlinJvmBinaryClass = FileBasedKotlinClass.create(byteContent) { name, classVersion, header, innerClasses ->
|
||||
VirtualFileKotlinClass(file, name, classVersion, header, innerClasses)
|
||||
}
|
||||
|
||||
return@time kotlinJvmBinaryClass?.let(::KotlinClass)
|
||||
?: KotlinClassFinder.Result.ClassFileContent(byteContent)
|
||||
}
|
||||
}
|
||||
catch (e: FileNotFoundException) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.load.kotlin.findKotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||
|
||||
@@ -87,5 +87,5 @@ fun getSourceElement(descriptor: DeclarationDescriptor): SourceElement =
|
||||
descriptor.toSourceElement
|
||||
}
|
||||
|
||||
private val DeclarationDescriptor.toSourceElement: SourceElement
|
||||
val DeclarationDescriptor.toSourceElement: SourceElement
|
||||
get() = if (this is DeclarationDescriptorWithSource) source else SourceElement.NO_SOURCE
|
||||
|
||||
@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.resolve.jvm
|
||||
|
||||
import com.intellij.psi.impl.file.impl.JavaFileManager
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
interface KotlinCliJavaFileManager : JavaFileManager {
|
||||
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass?
|
||||
fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass?
|
||||
fun knownClassNamesInPackage(packageFqName: FqName): Set<String>?
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.asJava.KtLightClassMarker;
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage;
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder;
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinderImpl;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass;
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl;
|
||||
@@ -104,9 +105,10 @@ public class KotlinJavaPsiFacade {
|
||||
return emptyModifierList;
|
||||
}
|
||||
|
||||
public JavaClass findClass(@NotNull ClassId classId, @NotNull GlobalSearchScope scope) {
|
||||
public JavaClass findClass(@NotNull JavaClassFinder.Request request, @NotNull GlobalSearchScope scope) {
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
|
||||
|
||||
ClassId classId = request.getClassId();
|
||||
String qualifiedName = classId.asSingleFqName().asString();
|
||||
|
||||
if (shouldUseSlowResolve()) {
|
||||
@@ -119,7 +121,7 @@ public class KotlinJavaPsiFacade {
|
||||
|
||||
for (KotlinPsiElementFinderWrapper finder : finders()) {
|
||||
if (finder instanceof CliFinder) {
|
||||
JavaClass aClass = ((CliFinder) finder).findClass(classId, scope);
|
||||
JavaClass aClass = ((CliFinder) finder).findClass(request, scope);
|
||||
if (aClass != null) return aClass;
|
||||
}
|
||||
else {
|
||||
@@ -383,8 +385,8 @@ public class KotlinJavaPsiFacade {
|
||||
return javaFileManager.findClass(qualifiedName, scope);
|
||||
}
|
||||
|
||||
public JavaClass findClass(@NotNull ClassId classId, @NotNull GlobalSearchScope scope) {
|
||||
return javaFileManager.findClass(classId, scope);
|
||||
public JavaClass findClass(@NotNull JavaClassFinder.Request request, @NotNull GlobalSearchScope scope) {
|
||||
return javaFileManager.findClass(request, scope);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
/**
|
||||
* This checker detects if call by operator convention to a Java method violates some expected contract:
|
||||
* - "key in map" commonly resolves to an stdlib extension that calls Map.containsKey(),
|
||||
* but there's a member in ConcurrentHashMap with acceptable signature that delegates to `containsValue` instead
|
||||
*/
|
||||
object InconsistentOperatorFromJavaCallChecker : CallChecker {
|
||||
private val CONCURRENT_HASH_MAP_FQ_NAME = FqName("java.util.concurrent.ConcurrentHashMap")
|
||||
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val candidateDescriptor = resolvedCall.candidateDescriptor
|
||||
if (candidateDescriptor.name != OperatorNameConventions.CONTAINS) return
|
||||
if (candidateDescriptor.valueParameters.singleOrNull()?.type?.isAnyOrNullableAny() != true) return
|
||||
if (resolvedCall.call.callElement !is KtBinaryExpression || !resolvedCall.status.possibleTransformToSuccess()) return
|
||||
|
||||
for (callableDescriptor in candidateDescriptor.overriddenTreeUniqueAsSequence(useOriginal = false)) {
|
||||
val containingClass = callableDescriptor.containingDeclaration as? ClassDescriptor ?: continue
|
||||
if (containingClass.fqNameOrNull() != CONCURRENT_HASH_MAP_FQ_NAME) continue
|
||||
|
||||
val diagnosticFactory =
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitConcurrentHashMapContains))
|
||||
ErrorsJvm.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR
|
||||
else
|
||||
ErrorsJvm.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR
|
||||
|
||||
context.trace.report(diagnosticFactory.on(reportOn))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithCorrespondingExpectedDefault
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.VOLATILE_ANNOTATION_FQ_NAME
|
||||
@@ -194,21 +195,34 @@ class OverloadsAnnotationChecker: DeclarationChecker {
|
||||
descriptor.findJvmOverloadsAnnotation()?.let { annotation ->
|
||||
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation)
|
||||
if (annotationEntry != null) {
|
||||
checkDeclaration(annotationEntry, descriptor, context.trace)
|
||||
checkDeclaration(annotationEntry, descriptor, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkDeclaration(annotationEntry: KtAnnotationEntry, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) {
|
||||
private fun checkDeclaration(
|
||||
annotationEntry: KtAnnotationEntry,
|
||||
descriptor: DeclarationDescriptor,
|
||||
context: DeclarationCheckerContext
|
||||
) {
|
||||
val diagnosticHolder = context.trace
|
||||
|
||||
if (descriptor !is CallableDescriptor) {
|
||||
return
|
||||
}
|
||||
if ((descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE) {
|
||||
} else if ((descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE) {
|
||||
diagnosticHolder.report(ErrorsJvm.OVERLOADS_INTERFACE.on(annotationEntry))
|
||||
} else if (descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT) {
|
||||
diagnosticHolder.report(ErrorsJvm.OVERLOADS_ABSTRACT.on(annotationEntry))
|
||||
} else if (DescriptorUtils.isLocal(descriptor)) {
|
||||
diagnosticHolder.report(ErrorsJvm.OVERLOADS_LOCAL.on(annotationEntry))
|
||||
} else if (descriptor.isAnnotationConstructor()) {
|
||||
val diagnostic =
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses))
|
||||
ErrorsJvm.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR
|
||||
else
|
||||
ErrorsJvm.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING
|
||||
|
||||
diagnosticHolder.report(diagnostic.on(annotationEntry))
|
||||
} else if (!descriptor.visibility.isPublicAPI && descriptor.visibility != Visibilities.INTERNAL) {
|
||||
diagnosticHolder.report(ErrorsJvm.OVERLOADS_PRIVATE.on(annotationEntry))
|
||||
} else if (descriptor.valueParameters.none { it.declaresDefaultValue() || it.isActualParameterWithCorrespondingExpectedDefault }) {
|
||||
|
||||
@@ -50,6 +50,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(OVERLOADS_INTERFACE, "'@JvmOverloads' annotation cannot be used on interface methods");
|
||||
MAP.put(OVERLOADS_PRIVATE, "'@JvmOverloads' annotation has no effect on private declarations");
|
||||
MAP.put(OVERLOADS_LOCAL, "'@JvmOverloads' annotation cannot be used on local declarations");
|
||||
MAP.put(OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING, "'@JvmOverloads' annotation on constructors of annotation classes is deprecated");
|
||||
MAP.put(OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR, "'@JvmOverloads' annotation cannot be used on constructors of annotation classes");
|
||||
MAP.put(INAPPLICABLE_JVM_NAME, "'@JvmName' annotation is not applicable to this declaration");
|
||||
MAP.put(ILLEGAL_JVM_NAME, "Illegal JVM name");
|
||||
MAP.put(VOLATILE_ON_VALUE, "'@Volatile' annotation cannot be used on immutable properties");
|
||||
@@ -138,6 +140,13 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(EXPLICIT_METADATA_IS_DISALLOWED, "Explicit @Metadata is disallowed");
|
||||
MAP.put(SUSPENSION_POINT_INSIDE_MONITOR, "A suspension point at {0} is inside a critical section", STRING);
|
||||
MAP.put(SUSPENSION_POINT_INSIDE_SYNCHRONIZED, "The ''{0}'' suspension point is inside a synchronized block", NAME);
|
||||
|
||||
String MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS =
|
||||
"Method 'contains' from ConcurrentHashMap may have unexpected semantics: it calls 'containsValue' instead of 'containsKey'. " +
|
||||
"Use explicit form of the call to 'containsKey'/'containsValue'/'contains' or cast the value to kotlin.collections.Map instead. " +
|
||||
"See https://youtrack.jetbrains.com/issue/KT-18053 for more details";
|
||||
MAP.put(CONCURRENT_HASH_MAP_CONTAINS_OPERATOR, MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS);
|
||||
MAP.put(CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR, MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -54,6 +54,9 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_PRIVATE = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_LOCAL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
|
||||
DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT = DiagnosticFactory0.create(ERROR, ABSTRACT_MODIFIER);
|
||||
DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_HAVE_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
@@ -125,6 +128,9 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory1<PsiElement, String> SUSPENSION_POINT_INSIDE_MONITOR = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, CallableDescriptor> SUSPENSION_POINT_INSIDE_SYNCHRONIZED = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<PsiElement> CONCURRENT_HASH_MAP_CONTAINS_OPERATOR = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<PsiElement> CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
{
|
||||
|
||||
@@ -50,7 +50,8 @@ object JvmPlatformConfigurator : PlatformConfigurator(
|
||||
ProtectedSyntheticExtensionCallChecker,
|
||||
ReifiedTypeParameterSubstitutionChecker(),
|
||||
RuntimeAssertionsOnExtensionReceiverCallChecker,
|
||||
ApiVersionIsAtLeastArgumentsChecker
|
||||
ApiVersionIsAtLeastArgumentsChecker,
|
||||
InconsistentOperatorFromJavaCallChecker
|
||||
),
|
||||
|
||||
additionalTypeCheckers = listOf(
|
||||
|
||||
@@ -92,7 +92,7 @@ interface SyntheticJavaPropertyDescriptor : PropertyDescriptor, SyntheticPropert
|
||||
}
|
||||
}
|
||||
|
||||
class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val lookupTracker: LookupTracker) : SyntheticScope {
|
||||
class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val lookupTracker: LookupTracker) : SyntheticScope.Default() {
|
||||
private val syntheticPropertyInClass =
|
||||
storageManager.createMemoizedFunction<Pair<ClassDescriptor, Name>, SyntheticPropertyHolder> { pair ->
|
||||
syntheticPropertyInClassNotCached(pair.first, pair.second)
|
||||
@@ -205,18 +205,6 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyntheticStaticFunctions(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> =
|
||||
emptyList()
|
||||
|
||||
override fun getSyntheticConstructors(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> =
|
||||
emptyList()
|
||||
|
||||
override fun getSyntheticStaticFunctions(scope: ResolutionScope): Collection<FunctionDescriptor> = emptyList()
|
||||
|
||||
override fun getSyntheticConstructors(scope: ResolutionScope): Collection<FunctionDescriptor> = emptyList()
|
||||
|
||||
override fun getSyntheticConstructor(constructor: ConstructorDescriptor): ConstructorDescriptor? = null
|
||||
|
||||
private fun collectSyntheticPropertiesByName(
|
||||
result: SmartList<PropertyDescriptor>?,
|
||||
type: TypeConstructor,
|
||||
@@ -239,7 +227,10 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>): Collection<PropertyDescriptor> {
|
||||
override fun getSyntheticExtensionProperties(
|
||||
receiverTypes: Collection<KotlinType>,
|
||||
location: LookupLocation
|
||||
): Collection<PropertyDescriptor> {
|
||||
val result = ArrayList<PropertyDescriptor>()
|
||||
val processedTypes = HashSet<TypeConstructor>()
|
||||
receiverTypes.forEach { result.collectSyntheticProperties(it.constructor, processedTypes) }
|
||||
|
||||
@@ -16,25 +16,46 @@
|
||||
|
||||
package org.jetbrains.kotlin.synthetic
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.load.java.components.SamConversionResolver
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
class JavaSyntheticScopes(
|
||||
private val project: Project,
|
||||
private val moduleDescriptor: ModuleDescriptor,
|
||||
storageManager: StorageManager,
|
||||
lookupTracker: LookupTracker,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
samConventionResolver: SamConversionResolver,
|
||||
deprecationResolver: DeprecationResolver
|
||||
): SyntheticScopes {
|
||||
override val scopes = listOf(
|
||||
JavaSyntheticPropertiesScope(storageManager, lookupTracker),
|
||||
override val scopes = run {
|
||||
val javaSyntheticPropertiesScope = JavaSyntheticPropertiesScope(storageManager, lookupTracker)
|
||||
|
||||
val scopesFromExtensions = SyntheticScopeProviderExtension
|
||||
.getInstances(project)
|
||||
.flatMap { it.getScopes(moduleDescriptor, javaSyntheticPropertiesScope) }
|
||||
|
||||
listOf(
|
||||
javaSyntheticPropertiesScope,
|
||||
SamAdapterFunctionsScope(
|
||||
storageManager, languageVersionSettings, samConventionResolver, deprecationResolver,
|
||||
lookupTracker
|
||||
storageManager, languageVersionSettings, samConventionResolver, deprecationResolver,
|
||||
lookupTracker
|
||||
)
|
||||
)
|
||||
) + scopesFromExtensions
|
||||
}
|
||||
}
|
||||
|
||||
interface SyntheticScopeProviderExtension {
|
||||
companion object : ProjectExtensionDescriptor<SyntheticScopeProviderExtension>(
|
||||
"org.jetbrains.kotlin.syntheticScopeProviderExtension", SyntheticScopeProviderExtension::class.java)
|
||||
|
||||
fun getScopes(moduleDescriptor: ModuleDescriptor, javaSyntheticPropertiesScope: JavaSyntheticPropertiesScope): List<SyntheticScope>
|
||||
}
|
||||
@@ -59,7 +59,7 @@ class SamAdapterFunctionsScope(
|
||||
private val samResolver: SamConversionResolver,
|
||||
private val deprecationResolver: DeprecationResolver,
|
||||
private val lookupTracker: LookupTracker
|
||||
) : SyntheticScope {
|
||||
) : SyntheticScope.Default() {
|
||||
private val samViaSyntheticScopeDisabled = languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
|
||||
|
||||
private val extensionForFunction =
|
||||
@@ -150,10 +150,6 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<PropertyDescriptor> = emptyList()
|
||||
|
||||
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>): Collection<PropertyDescriptor> = emptyList()
|
||||
|
||||
override fun getSyntheticStaticFunctions(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
if (samViaSyntheticScopeDisabled) return emptyList()
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.script
|
||||
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
import kotlin.reflect.jvm.jvmErasure
|
||||
@@ -160,18 +159,6 @@ private class StringArgsConverter : ArgsConverter<String> {
|
||||
|
||||
override fun tryConvertVararg(parameter: KParameter, firstArg: NamedArgument<String>, restArgsIt: Iterator<NamedArgument<String>>): ArgsConverter.Result {
|
||||
|
||||
fun convertAnyArray(classifier: KClassifier?, args: Sequence<String?>): Any? =
|
||||
when (classifier) {
|
||||
String::class -> args.toList().toTypedArray()
|
||||
is KClass<*> -> classifier.constructors.firstNotNullResult { ctor ->
|
||||
try {
|
||||
args.map { ctor.call(it) }.toList().toTypedArray()
|
||||
}
|
||||
catch (e: Exception) { null }
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun convertPrimitivesArray(type: KType, args: Sequence<String?>): Any? =
|
||||
when (type.classifier) {
|
||||
IntArray::class -> args.map { it?.toIntOrNull() }
|
||||
@@ -228,9 +215,42 @@ private class AnyArgsConverter : ArgsConverter<Any> {
|
||||
?: ArgsConverter.Result.Failure
|
||||
}
|
||||
|
||||
override fun tryConvertVararg(parameter: KParameter, firstArg: NamedArgument<Any>, restArgsIt: Iterator<NamedArgument<Any>>): ArgsConverter.Result =
|
||||
ArgsConverter.Result.Failure
|
||||
override fun tryConvertVararg(
|
||||
parameter: KParameter, firstArg: NamedArgument<Any>, restArgsIt: Iterator<NamedArgument<Any>>
|
||||
): ArgsConverter.Result {
|
||||
|
||||
val parameterType = parameter.type
|
||||
if (parameterType.jvmErasure.java.isArray) {
|
||||
val argsSequence = sequenceOf(firstArg.value) + restArgsIt.asSequence().map { it.value }
|
||||
val arrayElementType = parameterType.arguments.firstOrNull()?.type
|
||||
val arrayArgCandidate = convertAnyArray(arrayElementType?.classifier, argsSequence)
|
||||
if (arrayArgCandidate != null)
|
||||
return ArgsConverter.Result.Success(arrayArgCandidate)
|
||||
}
|
||||
|
||||
return ArgsConverter.Result.Failure
|
||||
}
|
||||
|
||||
override fun tryConvertTail(parameter: KParameter, firstArg: NamedArgument<Any>, restArgsIt: Iterator<NamedArgument<Any>>): ArgsConverter.Result =
|
||||
tryConvertSingle(parameter, firstArg)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private inline fun <reified T> convertAnyArray(classifier: KClassifier?, args: Sequence<T?>): Any? =
|
||||
if (classifier == T::class) args.toList().toTypedArray() // simple case
|
||||
else convertAnyArrayImpl<T>(classifier, args)
|
||||
|
||||
private fun <T> convertAnyArrayImpl(classifier: KClassifier?, args: Sequence<T?>): Any? {
|
||||
val elementClass = (classifier as? KClass<*>) ?: return null
|
||||
|
||||
val argsList = args.toList()
|
||||
val result = java.lang.reflect.Array.newInstance(elementClass.java, argsList.size)
|
||||
argsList.forEachIndexed { idx, arg ->
|
||||
try {
|
||||
java.lang.reflect.Array.set(result, idx, arg)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
return@convertAnyArrayImpl null
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -118,6 +118,29 @@ class ControlFlowInformationProvider private constructor(
|
||||
markAndCheckTailCalls()
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects returned expressions from current pseudocode.
|
||||
*
|
||||
* "Returned expression" here == "last expression" in *control-flow terms*. Intuitively,
|
||||
* it considers all execution paths, takes last expression on each path and returns them.
|
||||
*
|
||||
* More specifically, this function starts from EXIT instruction, and performs DFS-search
|
||||
* on reversed control-flow edges in a following manner:
|
||||
* - if the current instruction is a Return-instruction, then add it's expression to result
|
||||
* - if the current instruction is a Element-instruction, then add it's element to result
|
||||
* - if the current instruction is a Jump-instruction, then process it's predecessors
|
||||
* recursively
|
||||
*
|
||||
* NB. The second case (Element-instruction) means that notion of "returned expression"
|
||||
* here differs from what the language treats as "returned expression" (notably in the
|
||||
* presence of Unit-coercion). Example:
|
||||
*
|
||||
* fun foo() {
|
||||
* val x = 42
|
||||
* x.inc() // This call will be in a [returnedExpressions], even though this expression
|
||||
* // isn't actually returned
|
||||
* }
|
||||
*/
|
||||
private fun collectReturnExpressions(returnedExpressions: MutableCollection<KtElement>) {
|
||||
val instructions = pseudocode.instructions.toHashSet()
|
||||
val exitInstruction = pseudocode.exitInstruction
|
||||
@@ -135,15 +158,17 @@ class ControlFlowInformationProvider private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun visitJump(instruction: AbstractJumpInstruction) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
override fun visitUnconditionalJump(instruction: UnconditionalJumpInstruction) {
|
||||
redirectToPrevInstructions(instruction)
|
||||
}
|
||||
|
||||
override fun visitConditionalJump(instruction: ConditionalJumpInstruction) {
|
||||
redirectToPrevInstructions(instruction)
|
||||
}
|
||||
|
||||
// Note that there's no need to overload `visitThrowException`, because
|
||||
// it can never be a predecessor of EXIT (throwing always leads to ERROR)
|
||||
|
||||
private fun redirectToPrevInstructions(instruction: Instruction) {
|
||||
for (redirectInstruction in instruction.previousInstructions) {
|
||||
redirectInstruction.accept(this)
|
||||
@@ -160,6 +185,9 @@ class ControlFlowInformationProvider private constructor(
|
||||
|
||||
override fun visitInstruction(instruction: Instruction) {
|
||||
if (instruction is KtElementInstruction) {
|
||||
// Caveats:
|
||||
// - for empty block-bodies, read(Unit) is emitted and will be processed here
|
||||
// - for Unit-coerced blocks, last expression will be processed here
|
||||
returnedExpressions.add(instruction.element)
|
||||
} else {
|
||||
throw IllegalStateException("$instruction precedes the exit point")
|
||||
|
||||
@@ -101,7 +101,9 @@ public interface Errors {
|
||||
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_BASE_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_STANDARD_TEMPLATE = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_RECEIVER_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> MISSING_IMPORTED_SCRIPT_FILE = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> MISSING_IMPORTED_SCRIPT_PSI = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> PRE_RELEASE_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<PsiElement, String, IncompatibleVersionErrorData<?>> INCOMPATIBLE_CLASS = DiagnosticFactory2.create(ERROR);
|
||||
|
||||
@@ -952,6 +954,8 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtTypeReference> LOCAL_EXTENSION_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtPropertyAccessor> LOCAL_VARIABLE_WITH_GETTER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtPropertyAccessor> LOCAL_VARIABLE_WITH_SETTER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeParameterList> LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtTypeParameterList> LOCAL_VARIABLE_WITH_TYPE_PARAMETERS = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory3<KtExpression, DeclarationDescriptor, Visibility, DeclarationDescriptor> INVISIBLE_SETTER = DiagnosticFactory3.create(ERROR);
|
||||
|
||||
|
||||
@@ -365,7 +365,9 @@ public class DefaultErrorMessages {
|
||||
MAP.put(MISSING_SCRIPT_BASE_CLASS, "Cannot access script base class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
||||
MAP.put(MISSING_SCRIPT_STANDARD_TEMPLATE, "No script runtime was found in the classpath: class ''{0}'' not found. Please add kotlin-script-runtime.jar to the module dependencies.", TO_STRING);
|
||||
MAP.put(MISSING_SCRIPT_RECEIVER_CLASS, "Cannot access implicit script receiver class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
||||
MAP.put(MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS, "Cannot access script environment property class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
||||
MAP.put(MISSING_IMPORTED_SCRIPT_FILE, "Cannot find imported script file ''{0}''. Check your script imports", TO_STRING);
|
||||
MAP.put(MISSING_IMPORTED_SCRIPT_PSI, "Imported script file ''{0}'' is not loaded. Check your script imports", TO_STRING);
|
||||
MAP.put(MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS, "Cannot access script provided property class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING);
|
||||
MAP.put(PRE_RELEASE_CLASS, "{0} is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler", TO_STRING);
|
||||
MAP.put(INCOMPATIBLE_CLASS,
|
||||
"{0} was compiled with an incompatible version of Kotlin. {1}",
|
||||
@@ -397,6 +399,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(LOCAL_EXTENSION_PROPERTY, "Local extension properties are not allowed");
|
||||
MAP.put(LOCAL_VARIABLE_WITH_GETTER, "Local variables are not allowed to have getters");
|
||||
MAP.put(LOCAL_VARIABLE_WITH_SETTER, "Local variables are not allowed to have setters");
|
||||
MAP.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING, "Type parameters for local variables are deprecated");
|
||||
MAP.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS, "Local variables are not allowed to have type parameters");
|
||||
MAP.put(VAL_WITH_SETTER, "A 'val'-property cannot have a setter");
|
||||
|
||||
MAP.put(DEPRECATED_IDENTITY_EQUALS, "Identity equality for arguments of types {0} and {1} is deprecated", RENDER_TYPE, RENDER_TYPE);
|
||||
|
||||
@@ -122,7 +122,8 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
|
||||
PropertiesWithBackingFieldsInsideInlineClass(),
|
||||
AnnotationClassTargetAndRetentionChecker(),
|
||||
ReservedMembersAndConstructsForInlineClass(),
|
||||
ResultClassInReturnTypeChecker()
|
||||
ResultClassInReturnTypeChecker(),
|
||||
LocalVariableTypeParametersChecker()
|
||||
)
|
||||
|
||||
private val DEFAULT_CALL_CHECKERS = listOf(
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
|
||||
class LocalVariableTypeParametersChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (declaration !is KtProperty || descriptor !is LocalVariableDescriptor) return
|
||||
|
||||
val typeParameters = declaration.typeParameters
|
||||
val typeParametersList = declaration.typeParameterList
|
||||
if (typeParameters.isEmpty() || typeParametersList == null) return
|
||||
|
||||
val diagnostic =
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitTypeParametersForLocalVariables))
|
||||
Errors.LOCAL_VARIABLE_WITH_TYPE_PARAMETERS
|
||||
else
|
||||
Errors.LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING
|
||||
|
||||
context.trace.report(diagnostic.on(typeParametersList))
|
||||
}
|
||||
}
|
||||
@@ -41,10 +41,13 @@ class LazyScriptClassMemberScope(
|
||||
if (baseConstructorDescriptor != null) {
|
||||
val implicitReceiversParamTypes =
|
||||
scriptDescriptor.implicitReceivers.mapIndexed { idx, receiver ->
|
||||
"$IMPLICIT_RECEIVER_PARAM_NAME_PREFIX$idx" to receiver.defaultType
|
||||
val name =
|
||||
if (receiver is ScriptDescriptor) "$IMPORTED_SCRIPT_PARAM_NAME_PREFIX${receiver.name}"
|
||||
else "$IMPLICIT_RECEIVER_PARAM_NAME_PREFIX$idx"
|
||||
name to receiver.defaultType
|
||||
}
|
||||
val environmentVarsParamTypes =
|
||||
scriptDescriptor.scriptEnvironmentProperties.map {
|
||||
val providedPropertiesParamTypes =
|
||||
scriptDescriptor.scriptProvidedProperties.map {
|
||||
it.name.identifier to it.type
|
||||
}
|
||||
val annotations = baseConstructorDescriptor.annotations
|
||||
@@ -53,7 +56,7 @@ class LazyScriptClassMemberScope(
|
||||
)
|
||||
var paramsIndexBase = baseConstructorDescriptor.valueParameters.lastIndex + 1
|
||||
val syntheticParameters =
|
||||
(implicitReceiversParamTypes + environmentVarsParamTypes).map { param: Pair<String, KotlinType> ->
|
||||
(implicitReceiversParamTypes + providedPropertiesParamTypes).map { param: Pair<String, KotlinType> ->
|
||||
ValueParameterDescriptorImpl(
|
||||
constructorDescriptor,
|
||||
null,
|
||||
@@ -103,6 +106,7 @@ class LazyScriptClassMemberScope(
|
||||
|
||||
companion object {
|
||||
const val IMPLICIT_RECEIVER_PARAM_NAME_PREFIX = "\$\$implicitReceiver"
|
||||
const val IMPORTED_SCRIPT_PARAM_NAME_PREFIX = "\$\$importedScript"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,17 +16,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.lazy.descriptors
|
||||
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.openapi.vfs.local.CoreLocalFileSystem
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -37,17 +40,20 @@ import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.lazy.data.KtScriptInfo
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ReplResultPropertyDescriptor
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptEnvironmentDescriptor
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.ScriptProvidedPropertiesDescriptor
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.script.classId
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeImpl
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
||||
import org.jetbrains.kotlin.script.ScriptPriorities
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.io.File
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
|
||||
@@ -143,10 +149,48 @@ class LazyScriptDescriptor(
|
||||
|
||||
override fun computeSupertypes() = listOf(baseClassDescriptor()?.defaultType ?: builtIns.anyType)
|
||||
|
||||
private inner class ImportedScriptDescriptorsFinder {
|
||||
|
||||
val fileManager = VirtualFileManager.getInstance()
|
||||
val localFS = fileManager.getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
||||
val psiManager = PsiManager.getInstance(scriptInfo.script.project)
|
||||
|
||||
operator fun invoke(importedScriptFile: File): ScriptDescriptor? {
|
||||
|
||||
fun errorDescriptor(errorDiagnostic: DiagnosticFactory1<PsiElement, String>?): ScriptDescriptor? {
|
||||
reportErrorString1(errorDiagnostic, importedScriptFile.path)
|
||||
return null
|
||||
}
|
||||
|
||||
val vfile = localFS.findFileByPath(importedScriptFile.path)
|
||||
?: return errorDescriptor(MISSING_IMPORTED_SCRIPT_FILE)
|
||||
val psiFile = psiManager.findFile(vfile)
|
||||
?: return errorDescriptor(MISSING_IMPORTED_SCRIPT_PSI)
|
||||
// Note: is not an error now - if import references other valid source file, it is simply compiled along with script
|
||||
// TODO: check if this is the behavior we want to have - see #KT-28916
|
||||
val ktScript = (psiFile as? KtFile)?.declarations?.firstIsInstanceOrNull<KtScript>()
|
||||
?: return null
|
||||
return resolveSession.getScriptDescriptor(ktScript)
|
||||
}
|
||||
}
|
||||
|
||||
private val scriptImplicitReceivers: () -> List<ClassDescriptor> = resolveSession.storageManager.createLazyValue {
|
||||
scriptDefinition().implicitReceivers.mapNotNull { receiver ->
|
||||
val res = ArrayList<ClassDescriptor>()
|
||||
|
||||
val importedScriptsFiles = ScriptDependenciesProvider.getInstance(scriptInfo.script.project)
|
||||
.getScriptDependencies(scriptInfo.script.containingKtFile)?.scripts
|
||||
if (importedScriptsFiles != null) {
|
||||
val findImportedScriptDescriptor = ImportedScriptDescriptorsFinder()
|
||||
importedScriptsFiles.mapNotNullTo(res) {
|
||||
findImportedScriptDescriptor(it)
|
||||
}
|
||||
}
|
||||
|
||||
scriptDefinition().implicitReceivers.mapNotNullTo(res) { receiver ->
|
||||
findTypeDescriptor(receiver, Errors.MISSING_SCRIPT_RECEIVER_CLASS)
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
internal fun findTypeDescriptor(kClass: KClass<*>, errorDiagnostic: DiagnosticFactory1<PsiElement, String>?): ClassDescriptor? =
|
||||
@@ -160,33 +204,39 @@ class LazyScriptDescriptor(
|
||||
errorDiagnostic: DiagnosticFactory1<PsiElement, String>?
|
||||
): ClassDescriptor? {
|
||||
val typeDescriptor = classId?.let { module.findClassAcrossModuleDependencies(it) }
|
||||
if (typeDescriptor == null && errorDiagnostic != null) {
|
||||
// TODO: use PositioningStrategies to highlight some specific place in case of error, instead of treating the whole file as invalid
|
||||
resolveSession.trace.report(
|
||||
errorDiagnostic.on(
|
||||
scriptInfo.script,
|
||||
classId?.asSingleFqName()?.toString() ?: typeName
|
||||
)
|
||||
)
|
||||
if (typeDescriptor == null) {
|
||||
reportErrorString1(errorDiagnostic, classId?.asSingleFqName()?.toString() ?: typeName)
|
||||
}
|
||||
return typeDescriptor
|
||||
}
|
||||
|
||||
override fun getImplicitReceivers(): List<ClassDescriptor> = scriptImplicitReceivers()
|
||||
|
||||
private val scriptEnvironment: () -> ScriptEnvironmentDescriptor = resolveSession.storageManager.createLazyValue {
|
||||
ScriptEnvironmentDescriptor(this)
|
||||
private fun reportErrorString1(errorDiagnostic: DiagnosticFactory1<PsiElement, String>?, arg: String) {
|
||||
if (errorDiagnostic != null) {
|
||||
// TODO: use PositioningStrategies to highlight some specific place in case of error, instead of treating the whole file as invalid
|
||||
resolveSession.trace.report(
|
||||
errorDiagnostic.on(
|
||||
scriptInfo.script,
|
||||
arg
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getScriptEnvironmentProperties(): List<PropertyDescriptor> = scriptEnvironment().properties()
|
||||
override fun getImplicitReceivers(): List<ClassDescriptor> = scriptImplicitReceivers()
|
||||
|
||||
private val scriptProvidedProperties: () -> ScriptProvidedPropertiesDescriptor = resolveSession.storageManager.createLazyValue {
|
||||
ScriptProvidedPropertiesDescriptor(this)
|
||||
}
|
||||
|
||||
override fun getScriptProvidedProperties(): List<PropertyDescriptor> = scriptProvidedProperties().properties()
|
||||
|
||||
private val scriptOuterScope: () -> LexicalScope = resolveSession.storageManager.createLazyValue {
|
||||
var outerScope = super.getOuterScope()
|
||||
val outerScopeReceivers = implicitReceivers.let {
|
||||
if (scriptDefinition().environmentVariables.isEmpty()) {
|
||||
if (scriptDefinition().providedProperties.isEmpty()) {
|
||||
it
|
||||
} else {
|
||||
it + ScriptEnvironmentDescriptor(this)
|
||||
it + ScriptProvidedPropertiesDescriptor(this)
|
||||
}
|
||||
}
|
||||
for (receiverClassDescriptor in outerScopeReceivers.asReversed()) {
|
||||
|
||||
@@ -17,11 +17,11 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
class ScriptEnvironmentDescriptor(script: LazyScriptDescriptor) :
|
||||
class ScriptProvidedPropertiesDescriptor(script: LazyScriptDescriptor) :
|
||||
MutableClassDescriptor(
|
||||
script,
|
||||
ClassKind.CLASS, false, false,
|
||||
Name.special("<synthetic script environment for ${script.name}>"),
|
||||
Name.special("<synthetic script provided properties for ${script.name}>"),
|
||||
SourceElement.NO_SOURCE,
|
||||
LockBasedStorageManager.NO_LOCKS
|
||||
) {
|
||||
@@ -33,8 +33,8 @@ class ScriptEnvironmentDescriptor(script: LazyScriptDescriptor) :
|
||||
createTypeConstructor()
|
||||
}
|
||||
|
||||
private val memberScope: () -> ScriptEnvironmentMemberScope = script.resolveSession.storageManager.createLazyValue {
|
||||
ScriptEnvironmentMemberScope(
|
||||
private val memberScope: () -> ScriptProvidedPropertiesMemberScope = script.resolveSession.storageManager.createLazyValue {
|
||||
ScriptProvidedPropertiesMemberScope(
|
||||
script.name.identifier,
|
||||
properties()
|
||||
)
|
||||
@@ -42,13 +42,13 @@ class ScriptEnvironmentDescriptor(script: LazyScriptDescriptor) :
|
||||
|
||||
override fun getUnsubstitutedMemberScope(): MemberScope = memberScope()
|
||||
|
||||
val properties: () -> List<ScriptEnvironmentPropertyDescriptor> = script.resolveSession.storageManager.createLazyValue {
|
||||
script.scriptDefinition().environmentVariables.mapNotNull { (name, type) ->
|
||||
script.findTypeDescriptor(type, Errors.MISSING_SCRIPT_ENVIRONMENT_PROPERTY_CLASS)?.let {
|
||||
val properties: () -> List<ScriptProvidedPropertyDescriptor> = script.resolveSession.storageManager.createLazyValue {
|
||||
script.scriptDefinition().providedProperties.mapNotNull { (name, type) ->
|
||||
script.findTypeDescriptor(type, Errors.MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS)?.let {
|
||||
name to it
|
||||
}
|
||||
}.map { (name, classDescriptor) ->
|
||||
ScriptEnvironmentPropertyDescriptor(
|
||||
ScriptProvidedPropertyDescriptor(
|
||||
Name.identifier(name),
|
||||
classDescriptor,
|
||||
thisAsReceiverParameter,
|
||||
@@ -58,21 +58,21 @@ class ScriptEnvironmentDescriptor(script: LazyScriptDescriptor) :
|
||||
}
|
||||
}
|
||||
|
||||
private class ScriptEnvironmentMemberScope(
|
||||
private class ScriptProvidedPropertiesMemberScope(
|
||||
private val scriptId: String,
|
||||
private val environmentProperties: List<PropertyDescriptor>
|
||||
private val providedProperties: List<PropertyDescriptor>
|
||||
) : MemberScopeImpl() {
|
||||
override fun getContributedDescriptors(
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Collection<DeclarationDescriptor> =
|
||||
environmentProperties
|
||||
providedProperties
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> =
|
||||
environmentProperties.filter { it.name == name }
|
||||
providedProperties.filter { it.name == name }
|
||||
|
||||
override fun printScopeStructure(p: Printer) {
|
||||
p.println("Scope of script environment: $scriptId")
|
||||
p.println("Scope of script provided properties: $scriptId")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
|
||||
|
||||
class ScriptEnvironmentPropertyDescriptor(
|
||||
class ScriptProvidedPropertyDescriptor(
|
||||
name: Name,
|
||||
typeDescriptor: ClassDescriptor,
|
||||
receiver: ReceiverParameterDescriptor?,
|
||||
@@ -1053,16 +1053,16 @@ class ExpressionCodegen(
|
||||
} else {
|
||||
val classType = classReference.classType
|
||||
if (classType is CrIrType) {
|
||||
putJavaLangClassInstance(mv, classType.type)
|
||||
putJavaLangClassInstance(mv, classType.type, null, state)
|
||||
return
|
||||
} else {
|
||||
val type = classType.toKotlinType()
|
||||
if (TypeUtils.isTypeParameter(type)) {
|
||||
assert(TypeUtils.isReifiedTypeParameter(type)) { "Non-reified type parameter under ::class should be rejected by type checker: " + type }
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
|
||||
val kotlinType = classType.toKotlinType()
|
||||
if (TypeUtils.isTypeParameter(kotlinType)) {
|
||||
assert(TypeUtils.isReifiedTypeParameter(kotlinType)) { "Non-reified type parameter under ::class should be rejected by type checker: " + kotlinType }
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(kotlinType, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
|
||||
}
|
||||
|
||||
putJavaLangClassInstance(mv, typeMapper.mapType(type))
|
||||
putJavaLangClassInstance(mv, typeMapper.mapType(kotlinType), kotlinType, state)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.javac.components
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
||||
@@ -32,10 +32,12 @@ class JavacBasedClassFinder : AbstractJavaClassFinder() {
|
||||
super.initialize(trace, codeAnalyzer)
|
||||
}
|
||||
|
||||
override fun findClass(classId: ClassId) = javac.findClass(classId, javaSearchScope)
|
||||
override fun findClass(request: JavaClassFinder.Request) =
|
||||
// TODO: reuse previouslyFoundClassFileContent if it's possible in javac
|
||||
javac.findClass(request.classId, javaSearchScope)
|
||||
|
||||
override fun findPackage(fqName: FqName) = javac.findPackage(fqName, javaSearchScope)
|
||||
|
||||
override fun knownClassNamesInPackage(packageFqName: FqName) = javac.knownClassNamesInPackage(packageFqName)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,15 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.light.AbstractLightClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation;
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder;
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage;
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class serves as a workaround for usages of {@link JavaElementFinder#findClasses} which eventually only need names of files
|
||||
* containing the class. When queried for a package class (e.g. test/TestPackage), {@code findClasses} along with a
|
||||
@@ -111,4 +114,10 @@ public class FakeLightClassForFileOfPackage extends AbstractLightClass implement
|
||||
public LightClassOriginKind getOriginKind() {
|
||||
return LightClassOriginKind.SOURCE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<KtLightAbstractAnnotation> getGivenAnnotations() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,8 +362,13 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
||||
return InvalidLightClassDataHolder
|
||||
}
|
||||
|
||||
return classOrObject.containingKtFile.script?.let { KtLightClassForScript.getLightClassCachedValue(it).value }
|
||||
?: getLightClassCachedValue(classOrObject).value
|
||||
val containingScript = classOrObject.containingKtFile.script
|
||||
return when {
|
||||
!classOrObject.isLocal && containingScript != null ->
|
||||
KtLightClassForScript.getLightClassCachedValue(containingScript).value
|
||||
else ->
|
||||
getLightClassCachedValue(classOrObject).value
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<LightClassDataHolder.ForClass> {
|
||||
|
||||
@@ -2,9 +2,21 @@ package org.jetbrains.kotlin.asJava.classes
|
||||
|
||||
import com.intellij.lang.jvm.JvmModifier
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiImplUtil
|
||||
import com.intellij.psi.impl.light.LightIdentifier
|
||||
import com.intellij.psi.meta.PsiMetaData
|
||||
import com.intellij.psi.util.TypeConversionUtil
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.annotations.Nullable
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
|
||||
import org.jetbrains.kotlin.asJava.elements.psiType
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCallElement
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
@@ -35,6 +47,128 @@ class KtUltraLightNullabilityAnnotation(
|
||||
}
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.obtainLightAnnotations(
|
||||
ultraLightSupport: UltraLightSupport,
|
||||
parent: PsiElement
|
||||
): List<KtLightAbstractAnnotation> = annotations.map { KtUltraLightAnnotationForDescriptor(it, ultraLightSupport, parent) }
|
||||
|
||||
class KtUltraLightAnnotationForDescriptor(
|
||||
private val annotationDescriptor: AnnotationDescriptor,
|
||||
private val ultraLightSupport: UltraLightSupport,
|
||||
parent: PsiElement
|
||||
) : KtLightAbstractAnnotation(parent, { error("clsDelegate for annotation based on descriptor: $annotationDescriptor") }) {
|
||||
override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = null
|
||||
|
||||
override fun getMetaData(): PsiMetaData? = null
|
||||
|
||||
private val parameterList = ParameterListImpl()
|
||||
|
||||
override fun getParameterList(): PsiAnnotationParameterList = parameterList
|
||||
|
||||
override val kotlinOrigin: KtCallElement? get() = null
|
||||
|
||||
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(p0: String?, p1: T?) = cannotModify()
|
||||
|
||||
override fun findAttributeValue(attributeName: String?): PsiAnnotationMemberValue? =
|
||||
PsiImplUtil.findAttributeValue(this, attributeName)
|
||||
|
||||
override fun findDeclaredAttributeValue(attributeName: String?) =
|
||||
PsiImplUtil.findDeclaredAttributeValue(this, attributeName)
|
||||
|
||||
override fun getQualifiedName() = annotationDescriptor.fqName?.asString()
|
||||
|
||||
private inner class ParameterListImpl : KtLightElementBase(this@KtUltraLightAnnotationForDescriptor), PsiAnnotationParameterList {
|
||||
private val _attributes: Array<PsiNameValuePair> by lazyPub {
|
||||
annotationDescriptor.allValueArguments.map {
|
||||
PsiNameValuePairForAnnotationArgument(it.key.asString(), it.value, ultraLightSupport, this)
|
||||
}.toTypedArray()
|
||||
}
|
||||
|
||||
override fun getAttributes(): Array<PsiNameValuePair> = _attributes
|
||||
|
||||
override val kotlinOrigin: KtElement? get() = null
|
||||
}
|
||||
|
||||
override fun getText() = "@$qualifiedName(" + parameterList.attributes.joinToString { it.name + "=" + it.value?.text } + ")"
|
||||
}
|
||||
|
||||
private class PsiNameValuePairForAnnotationArgument(
|
||||
private val _name: String = "",
|
||||
private val constantValue: ConstantValue<*>,
|
||||
private val ultraLightSupport: UltraLightSupport,
|
||||
parent: PsiElement
|
||||
) : KtLightElementBase(parent), PsiNameValuePair {
|
||||
override val kotlinOrigin: KtElement? get() = null
|
||||
|
||||
private val _value by lazyPub {
|
||||
constantValue.toAnnotationMemberValue(this, ultraLightSupport)
|
||||
}
|
||||
|
||||
override fun setValue(p0: PsiAnnotationMemberValue) = cannotModify()
|
||||
|
||||
override fun getNameIdentifier() = LightIdentifier(parent.manager, _name)
|
||||
|
||||
override fun getValue(): PsiAnnotationMemberValue? = _value
|
||||
|
||||
override fun getLiteralValue(): String? = (value as? PsiLiteralExpression)?.value?.toString()
|
||||
|
||||
override fun getName() = _name
|
||||
}
|
||||
|
||||
private fun ConstantValue<*>.toAnnotationMemberValue(
|
||||
parent: PsiElement, ultraLightSupport: UltraLightSupport
|
||||
): PsiAnnotationMemberValue? = when (this) {
|
||||
|
||||
is AnnotationValue -> KtUltraLightAnnotationForDescriptor(value, ultraLightSupport, parent)
|
||||
|
||||
is ArrayValue ->
|
||||
KtUltraLightPsiArrayInitializerMemberValue(lightParent = parent) { arrayLiteralParent ->
|
||||
this.value.mapNotNull { element -> element.toAnnotationMemberValue(arrayLiteralParent, ultraLightSupport) }
|
||||
}
|
||||
|
||||
is ErrorValue -> null
|
||||
else -> createPsiLiteral(parent)
|
||||
}
|
||||
|
||||
private fun ConstantValue<*>.createPsiLiteral(parent: PsiElement): PsiExpression? {
|
||||
val asString = asStringForPsiLiteral(parent)
|
||||
val instance = PsiElementFactory.SERVICE.getInstance(parent.project)
|
||||
return instance.createExpressionFromText(asString, parent)
|
||||
}
|
||||
|
||||
private fun ConstantValue<*>.asStringForPsiLiteral(parent: PsiElement): String =
|
||||
when (this) {
|
||||
is NullValue -> "null"
|
||||
is StringValue -> "\"$value\""
|
||||
is KClassValue -> {
|
||||
val arrayPart = "[]".repeat(value.arrayNestedness)
|
||||
val fqName = value.classId.asSingleFqName()
|
||||
val canonicalText = psiType(
|
||||
fqName.asString(), parent, boxPrimitiveType = value.arrayNestedness > 0
|
||||
).let(TypeConversionUtil::erasure).getCanonicalText(false)
|
||||
|
||||
"$canonicalText$arrayPart.class"
|
||||
}
|
||||
is EnumValue -> "${enumClassId.asSingleFqName().asString()}.$enumEntryName"
|
||||
else -> value.toString()
|
||||
}
|
||||
|
||||
|
||||
private class KtUltraLightPsiArrayInitializerMemberValue(
|
||||
val lightParent: PsiElement,
|
||||
private val arguments: (KtUltraLightPsiArrayInitializerMemberValue) -> List<PsiAnnotationMemberValue>
|
||||
) : KtLightElementBase(lightParent), PsiArrayInitializerMemberValue {
|
||||
|
||||
override val kotlinOrigin: KtElement? get() = null
|
||||
|
||||
override fun getInitializers(): Array<PsiAnnotationMemberValue> = arguments(this).toTypedArray()
|
||||
|
||||
override fun getParent(): PsiElement = lightParent
|
||||
override fun isPhysical(): Boolean = false
|
||||
|
||||
override fun getText(): String = "{" + initializers.joinToString { it.text } + "}"
|
||||
}
|
||||
|
||||
fun PsiModifierListOwner.isPrivateOrParameterInPrivateMethod(): Boolean {
|
||||
if (hasModifier(JvmModifier.PRIVATE)) return true
|
||||
if (this !is PsiParameter) return false
|
||||
|
||||
@@ -10,16 +10,19 @@ import com.intellij.psi.impl.PsiImplUtil
|
||||
import com.intellij.psi.impl.PsiSuperMethodImplUtil
|
||||
import com.intellij.psi.impl.light.LightMethodBuilder
|
||||
import com.intellij.psi.impl.light.LightTypeParameterListBuilder
|
||||
import com.intellij.psi.search.LocalSearchScope
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightSimpleModifierList
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
@@ -56,7 +59,8 @@ internal abstract class KtUltraLightMethod(
|
||||
val list = KotlinLightReferenceListBuilder(manager, language, PsiReferenceList.Role.THROWS_LIST)
|
||||
computeDescriptor()?.let {
|
||||
for (ex in FunctionCodegen.getThrownExceptions(it)) {
|
||||
list.addReference(ex.fqNameSafe.asString())
|
||||
val psiClassType = ex.defaultType.asPsiType(support, TypeMappingMode.DEFAULT, list) as? PsiClassType ?: continue
|
||||
list.addReference(psiClassType)
|
||||
}
|
||||
}
|
||||
list
|
||||
@@ -109,12 +113,15 @@ internal class KtUltraLightMethodForDescriptor(
|
||||
|
||||
override val kotlinTypeForNullabilityAnnotation: KotlinType?
|
||||
get() = descriptor.returnType
|
||||
|
||||
override val givenAnnotations: List<KtLightAbstractAnnotation>
|
||||
get() = descriptor.obtainLightAnnotations(support, this)
|
||||
}
|
||||
|
||||
internal abstract class KtUltraLightParameter(
|
||||
name: String,
|
||||
override val kotlinOrigin: KtDeclaration?,
|
||||
private val support: UltraLightSupport,
|
||||
protected val support: UltraLightSupport,
|
||||
method: KtLightMethod
|
||||
) : org.jetbrains.kotlin.asJava.elements.LightParameter(
|
||||
name,
|
||||
@@ -131,6 +138,7 @@ internal abstract class KtUltraLightParameter(
|
||||
override fun getModifierList(): PsiModifierList = lightModifierList
|
||||
|
||||
override fun getNavigationElement(): PsiElement = kotlinOrigin ?: method.navigationElement
|
||||
override fun getUseScope(): SearchScope = kotlinOrigin?.useScope ?: LocalSearchScope(this)
|
||||
|
||||
override fun isValid() = parent.isValid
|
||||
|
||||
@@ -246,4 +254,7 @@ internal class KtUltraLightParameterForDescriptor(
|
||||
override fun computeContainingDescriptor() = descriptor.containingDeclaration as? CallableMemberDescriptor
|
||||
|
||||
override fun isVarArgs() = (descriptor as? ValueParameterDescriptor)?.varargElementType != null
|
||||
|
||||
override val givenAnnotations: List<KtLightAbstractAnnotation>
|
||||
get() = descriptor.obtainLightAnnotations(support, this)
|
||||
}
|
||||
|
||||
@@ -377,6 +377,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
||||
private fun shouldGenerateNoArgOverload(primary: KtPrimaryConstructor): Boolean {
|
||||
return !primary.hasModifier(PRIVATE_KEYWORD) &&
|
||||
!classOrObject.hasModifier(INNER_KEYWORD) && !isEnum &&
|
||||
!classOrObject.hasModifier(SEALED_KEYWORD) &&
|
||||
primary.valueParameters.isNotEmpty() &&
|
||||
primary.valueParameters.all { it.defaultValue != null } &&
|
||||
classOrObject.allConstructors.none { it.valueParameters.isEmpty() }
|
||||
@@ -669,6 +670,8 @@ interface UltraLightSupport {
|
||||
fun findAnnotation(owner: KtAnnotated, fqName: FqName): Pair<KtAnnotationEntry, AnnotationDescriptor>?
|
||||
fun isTooComplexForUltraLightGeneration(element: KtClassOrObject): Boolean
|
||||
val deprecationResolver: DeprecationResolver
|
||||
val typeMapper: KotlinTypeMapper
|
||||
val moduleDescriptor: ModuleDescriptor
|
||||
}
|
||||
|
||||
interface KtUltraLightElementWithNullabilityAnnotation<out T : KtDeclaration, out D : PsiModifierListOwner> : KtLightDeclaration<T, D>,
|
||||
|
||||
@@ -18,21 +18,17 @@ import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -147,8 +143,16 @@ internal fun UltraLightSupport.mapType(
|
||||
mapTypeToSignatureWriter: (KotlinTypeMapper, JvmSignatureWriter) -> Unit
|
||||
): PsiType {
|
||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
|
||||
mapTypeToSignatureWriter(typeMapper(this), signatureWriter)
|
||||
val signature = StringCharacterIterator(signatureWriter.toString())
|
||||
mapTypeToSignatureWriter(typeMapper, signatureWriter)
|
||||
val canonicalSignature = signatureWriter.toString()
|
||||
return createTypeFromCanonicalText(canonicalSignature, psiContext)
|
||||
}
|
||||
|
||||
fun createTypeFromCanonicalText(
|
||||
canonicalSignature: String,
|
||||
psiContext: PsiElement
|
||||
): PsiType {
|
||||
val signature = StringCharacterIterator(canonicalSignature)
|
||||
|
||||
val javaType = SignatureParsing.parseTypeString(signature, StubBuildingVisitor.GUESSING_MAPPER)
|
||||
val typeInfo = TypeInfo.fromString(javaType, false)
|
||||
@@ -161,15 +165,6 @@ internal fun UltraLightSupport.mapType(
|
||||
return type
|
||||
}
|
||||
|
||||
internal fun typeMapper(support: UltraLightSupport): KotlinTypeMapper = KotlinTypeMapper(
|
||||
BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
|
||||
IncompatibleClassTracker.DoNothing, support.moduleName,
|
||||
JvmTarget.JVM_1_8,
|
||||
KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT, // TODO use proper LanguageVersionSettings
|
||||
false,
|
||||
KotlinType::cleanFromAnonymousTypes
|
||||
)
|
||||
|
||||
// Returns null when type is unchanged
|
||||
fun KotlinType.cleanFromAnonymousTypes(): KotlinType? {
|
||||
val returnTypeClass = constructor.declarationDescriptor as? ClassDescriptor ?: return null
|
||||
@@ -234,7 +229,7 @@ fun KtUltraLightClass.createGeneratedMethodFromDescriptor(
|
||||
private fun KtUltraLightClass.lightMethod(
|
||||
descriptor: FunctionDescriptor
|
||||
): LightMethodBuilder {
|
||||
val name = typeMapper(support).mapFunctionName(descriptor, OwnerKind.IMPLEMENTATION)
|
||||
val name = support.typeMapper.mapFunctionName(descriptor, OwnerKind.IMPLEMENTATION)
|
||||
|
||||
val accessFlags: Int by lazyPub {
|
||||
val asmFlags = AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION, support.deprecationResolver)
|
||||
|
||||
@@ -78,7 +78,7 @@ class KtLightPsiClassObjectAccessExpression(override val kotlinOrigin: KtClassLi
|
||||
override fun getOperand(): PsiTypeElement = LightTypeElement(kotlinOrigin.manager, type)
|
||||
}
|
||||
|
||||
private fun psiType(kotlinFqName: String, context: PsiElement, boxPrimitiveType: Boolean = false): PsiType? {
|
||||
internal fun psiType(kotlinFqName: String, context: PsiElement, boxPrimitiveType: Boolean = false): PsiType {
|
||||
if (!boxPrimitiveType) {
|
||||
when (kotlinFqName) {
|
||||
"kotlin.Int" -> return PsiType.INT
|
||||
@@ -132,4 +132,4 @@ class KtLightPsiNameValuePair private constructor(
|
||||
|
||||
override fun getLiteralValue(): String? = (getValue() as? PsiLiteralExpression)?.value?.toString()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class KtLightPsiClassObjectAccessExpression(override val kotlinOrigin: KtClassLi
|
||||
override fun getOperand(): PsiTypeElement = LightTypeElement(kotlinOrigin.manager, type)
|
||||
}
|
||||
|
||||
private fun psiType(kotlinFqName: String, context: PsiElement, boxPrimitiveType: Boolean = false): PsiType? {
|
||||
internal fun psiType(kotlinFqName: String, context: PsiElement, boxPrimitiveType: Boolean = false): PsiType {
|
||||
if (!boxPrimitiveType) {
|
||||
when (kotlinFqName) {
|
||||
"kotlin.Int" -> return PsiType.INT
|
||||
@@ -132,4 +132,4 @@ class KtLightPsiNameValuePair private constructor(
|
||||
|
||||
override fun getLiteralValue(): String? = (getValue() as? PsiLiteralExpression)?.value?.toString()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,14 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
interface KtLightElement<out T : KtElement, out D : PsiElement> : PsiElement {
|
||||
val kotlinOrigin: T?
|
||||
|
||||
/**
|
||||
* KtLightModifierList by default retrieves annotation from the relevant KtElement or from clsDelegate
|
||||
* But we have none of them for KtUltraLightAnnotationForDescriptor built upon descriptor
|
||||
* For that case, KtLightModifierList in the beginning checks `givenAnnotations` and uses them if it's not null
|
||||
* Probably, it's a bit dirty solution. But, for now it's not clear how to make it better
|
||||
*/
|
||||
val givenAnnotations: List<KtLightAbstractAnnotation>? get() = null
|
||||
|
||||
val clsDelegate: D
|
||||
}
|
||||
|
||||
@@ -46,4 +54,4 @@ interface KtLightMethod : PsiAnnotationMethod, KtLightMember<PsiMethod> {
|
||||
|| lightMemberOrigin?.originKind == JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL
|
||||
|
||||
val isMangled: Boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,8 @@ abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, P
|
||||
override fun toString() = "Light modifier list of $owner"
|
||||
|
||||
private fun computeAnnotations(): List<KtLightAbstractAnnotation> {
|
||||
val annotationsForEntries = lightAnnotationsForEntries(this)
|
||||
val annotationsForEntries =
|
||||
owner.givenAnnotations ?: lightAnnotationsForEntries(this)
|
||||
val modifierListOwner = parent
|
||||
if (modifierListOwner is KtLightClassForSourceDeclaration && modifierListOwner.isAnnotationType) {
|
||||
val sourceAnnotationNames = annotationsForEntries.mapTo(mutableSetOf()) { it.qualifiedName }
|
||||
|
||||
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.idea.KotlinLanguage;
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameter;
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KtLightTypeParameter
|
||||
extends AbstractLightClass implements PsiTypeParameter, KtLightDeclaration<KtTypeParameter, PsiTypeParameter> {
|
||||
private final PsiTypeParameterListOwner owner;
|
||||
@@ -172,4 +174,10 @@ public class KtLightTypeParameter
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<KtLightAbstractAnnotation> getGivenAnnotations() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,9 +157,13 @@ class KtLightAnnotationForSourceEntry(
|
||||
val valueArguments = callEntry.value.arguments
|
||||
val argument = valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
|
||||
|
||||
if (!callEntry.key.type.let { KotlinBuiltIns.isArray(it) }) return null
|
||||
if (!callEntry.key.type.let { KotlinBuiltIns.isArrayOrPrimitiveArray(it) }) return null
|
||||
|
||||
if (argument !is KtStringTemplateExpression && argument !is KtConstantExpression && getAnnotationName(argument) == null) {
|
||||
if (argument !is KtStringTemplateExpression &&
|
||||
argument !is KtConstantExpression &&
|
||||
argument !is KtClassLiteralExpression &&
|
||||
getAnnotationName(argument) == null
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -159,9 +159,13 @@ class KtLightAnnotationForSourceEntry(
|
||||
val valueArguments = callEntry.value.arguments
|
||||
val argument = valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
|
||||
|
||||
if (!callEntry.key.type.let { KotlinBuiltIns.isArray(it) }) return null
|
||||
if (!callEntry.key.type.let { KotlinBuiltIns.isArrayOrPrimitiveArray(it) }) return null
|
||||
|
||||
if (argument !is KtStringTemplateExpression && argument !is KtConstantExpression && getAnnotationName(argument) == null) {
|
||||
if (argument !is KtStringTemplateExpression &&
|
||||
argument !is KtConstantExpression &&
|
||||
argument !is KtClassLiteralExpression &&
|
||||
getAnnotationName(argument) == null
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.lang.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class KotlinLanguage extends Language {
|
||||
@NotNull
|
||||
public static final KotlinLanguage INSTANCE = new KotlinLanguage();
|
||||
public static final String NAME = "Kotlin";
|
||||
|
||||
|
||||
@@ -750,7 +750,10 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
*/
|
||||
private boolean parseAnnotation(AnnotationParsingMode mode) {
|
||||
assert _at(IDENTIFIER) ||
|
||||
(_at(AT) && !WHITE_SPACE_OR_COMMENT_BIT_SET.contains(myBuilder.rawLookup(1)));
|
||||
// We have "@ann" or "@:ann" or "@ :ann", but not "@ ann"
|
||||
// (it's guaranteed that call sites do not allow the latter case)
|
||||
(_at(AT) && (!isNextRawTokenCommentOrWhitespace() || lookahead(1) == COLON))
|
||||
: "Invalid annotation prefix";
|
||||
|
||||
PsiBuilder.Marker annotation = mark();
|
||||
|
||||
@@ -780,6 +783,10 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isNextRawTokenCommentOrWhitespace() {
|
||||
return WHITE_SPACE_OR_COMMENT_BIT_SET.contains(myBuilder.rawLookup(1));
|
||||
}
|
||||
|
||||
public enum NameParsingMode {
|
||||
REQUIRED,
|
||||
ALLOWED,
|
||||
|
||||
@@ -164,7 +164,8 @@ abstract class KtClassOrObject :
|
||||
val parts = mutableListOf<String>()
|
||||
var current: KtClassOrObject? = this
|
||||
while (current != null) {
|
||||
parts.add(current.name!!)
|
||||
val name = current.name ?: return null
|
||||
parts.add(name)
|
||||
current = PsiTreeUtil.getParentOfType(current, KtClassOrObject::class.java)
|
||||
}
|
||||
val file = containingFile as? KtFile ?: return null
|
||||
|
||||
@@ -804,6 +804,12 @@ public class KtPsiUtil {
|
||||
else if (parent instanceof KtClassBody && !isMemberOfObjectExpression((KtCallableDeclaration) current)) {
|
||||
return (KtElement) parent;
|
||||
}
|
||||
else if (parent instanceof KtBlockExpression) {
|
||||
PsiElement grandParent = parent.getParent();
|
||||
if (grandParent instanceof KtScript) {
|
||||
return (KtElement) parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (current instanceof KtParameter) {
|
||||
return (KtElement) current;
|
||||
|
||||
@@ -60,7 +60,7 @@ open class KotlinScriptDefinition(open val template: KClass<out Any>) : UserData
|
||||
|
||||
open val implicitReceivers: List<KType> get() = emptyList()
|
||||
|
||||
open val environmentVariables: List<Pair<String, KType>> get() = emptyList()
|
||||
open val providedProperties: List<Pair<String, KType>> get() = emptyList()
|
||||
|
||||
open val targetClassAnnotations: List<Annotation> get() = emptyList()
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ fun findScriptDefinition(file: VirtualFile, project: Project): KotlinScriptDefin
|
||||
if (file.isDirectory ||
|
||||
file.extension == KotlinFileType.EXTENSION ||
|
||||
file.extension == JavaClassFileType.INSTANCE.defaultExtension ||
|
||||
FileTypeRegistry.getInstance().getFileTypeByFileName(file.name) != KotlinFileType.INSTANCE
|
||||
!isKotlinFileType(file)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
@@ -67,6 +67,12 @@ fun findScriptDefinition(file: VirtualFile, project: Project): KotlinScriptDefin
|
||||
return scriptDefinitionProvider.findScriptDefinition(file.name)
|
||||
}
|
||||
|
||||
private fun isKotlinFileType(file: VirtualFile): Boolean {
|
||||
val typeRegistry = FileTypeRegistry.getInstance()
|
||||
return typeRegistry.getFileTypeByFile(file) == KotlinFileType.INSTANCE ||
|
||||
typeRegistry.getFileTypeByFileName(file.name) == KotlinFileType.INSTANCE
|
||||
}
|
||||
|
||||
abstract class LazyScriptDefinitionProvider : ScriptDefinitionProvider {
|
||||
|
||||
protected val lock = ReentrantReadWriteLock()
|
||||
@@ -121,11 +127,18 @@ private class CachingSequence<T>(from: Sequence<T>) : Sequence<T> {
|
||||
|
||||
private var cacheCursor = 0
|
||||
|
||||
override fun hasNext(): Boolean = lock.read { cacheCursor < cache.size || sequenceIterator.hasNext() }
|
||||
override fun hasNext(): Boolean =
|
||||
lock.read { cacheCursor < cache.size } || lock.write { cacheCursor < cache.size || sequenceIterator.hasNext() }
|
||||
|
||||
override fun next(): T = lock.write {
|
||||
if (cacheCursor < cache.size) cache[cacheCursor++]
|
||||
else sequenceIterator.next().also { cache.add(it) }
|
||||
override fun next(): T {
|
||||
lock.read {
|
||||
if (cacheCursor < cache.size) return cache[cacheCursor++]
|
||||
}
|
||||
// lock.write is not an upgrade but retake, therefore - one more check needed
|
||||
lock.write {
|
||||
return if (cacheCursor < cache.size) cache[cacheCursor++]
|
||||
else sequenceIterator.next().also { cache.add(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||
|
||||
interface ScriptDependenciesProvider {
|
||||
fun getScriptDependencies(file: VirtualFile): ScriptDependencies?
|
||||
fun getScriptDependencies(file: PsiFile) = getScriptDependencies(file.virtualFile)
|
||||
fun getScriptDependencies(file: PsiFile) = getScriptDependencies(file.virtualFile ?: file.originalFile.virtualFile)
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): ScriptDependenciesProvider =
|
||||
|
||||
@@ -108,17 +108,21 @@ class DescriptorSerializer private constructor(
|
||||
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue
|
||||
|
||||
when (descriptor) {
|
||||
is PropertyDescriptor -> builder.addProperty(propertyProto(descriptor))
|
||||
is FunctionDescriptor -> builder.addFunction(functionProto(descriptor))
|
||||
is PropertyDescriptor -> propertyProto(descriptor)?.let { builder.addProperty(it) }
|
||||
is FunctionDescriptor -> functionProto(descriptor)?.let { builder.addFunction(it) }
|
||||
}
|
||||
}
|
||||
|
||||
val nestedClassifiers = sort(DescriptorUtils.getAllDescriptors(classDescriptor.unsubstitutedInnerClassesScope))
|
||||
for (descriptor in nestedClassifiers) {
|
||||
if (descriptor is TypeAliasDescriptor) {
|
||||
builder.addTypeAlias(typeAliasProto(descriptor))
|
||||
typeAliasProto(descriptor)?.let { builder.addTypeAlias(it) }
|
||||
}
|
||||
else {
|
||||
if (descriptor is ClassDescriptor && !extension.shouldSerializeNestedClass(descriptor)) {
|
||||
continue
|
||||
}
|
||||
|
||||
val name = getSimpleNameIndex(descriptor.name)
|
||||
if (isEnumEntry(descriptor)) {
|
||||
builder.addEnumEntry(enumEntryProto(descriptor as ClassDescriptor))
|
||||
@@ -178,7 +182,9 @@ class DescriptorSerializer private constructor(
|
||||
return false
|
||||
}
|
||||
|
||||
fun propertyProto(descriptor: PropertyDescriptor): ProtoBuf.Property.Builder {
|
||||
fun propertyProto(descriptor: PropertyDescriptor): ProtoBuf.Property.Builder? {
|
||||
if (!extension.shouldSerializeProperty(descriptor)) return null
|
||||
|
||||
val builder = ProtoBuf.Property.newBuilder()
|
||||
|
||||
val local = createChildSerializer(descriptor)
|
||||
@@ -281,7 +287,9 @@ class DescriptorSerializer private constructor(
|
||||
else
|
||||
descriptor.visibility
|
||||
|
||||
fun functionProto(descriptor: FunctionDescriptor): ProtoBuf.Function.Builder {
|
||||
fun functionProto(descriptor: FunctionDescriptor): ProtoBuf.Function.Builder? {
|
||||
if (!extension.shouldSerializeFunction(descriptor)) return null
|
||||
|
||||
val builder = ProtoBuf.Function.newBuilder()
|
||||
|
||||
val local = createChildSerializer(descriptor)
|
||||
@@ -402,7 +410,9 @@ class DescriptorSerializer private constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun typeAliasProto(descriptor: TypeAliasDescriptor): ProtoBuf.TypeAlias.Builder {
|
||||
private fun typeAliasProto(descriptor: TypeAliasDescriptor): ProtoBuf.TypeAlias.Builder? {
|
||||
if (!extension.shouldSerializeTypeAlias(descriptor)) return null
|
||||
|
||||
val builder = ProtoBuf.TypeAlias.newBuilder()
|
||||
val local = createChildSerializer(descriptor)
|
||||
|
||||
@@ -638,9 +648,9 @@ class DescriptorSerializer private constructor(
|
||||
|
||||
for (declaration in sort(members)) {
|
||||
when (declaration) {
|
||||
is PropertyDescriptor -> builder.addProperty(propertyProto(declaration))
|
||||
is FunctionDescriptor -> builder.addFunction(functionProto(declaration))
|
||||
is TypeAliasDescriptor -> builder.addTypeAlias(typeAliasProto(declaration))
|
||||
is PropertyDescriptor -> propertyProto(declaration)?.let { builder.addProperty(it) }
|
||||
is FunctionDescriptor -> functionProto(declaration)?.let { builder.addFunction(it) }
|
||||
is TypeAliasDescriptor -> typeAliasProto(declaration)?.let { builder.addTypeAlias(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ abstract class SerializerExtension {
|
||||
|
||||
open fun shouldUseTypeTable(): Boolean = false
|
||||
open fun shouldUseNormalizedVisibility(): Boolean = false
|
||||
open fun shouldSerializeFunction(descriptor: FunctionDescriptor): Boolean = true
|
||||
open fun shouldSerializeProperty(descriptor: PropertyDescriptor): Boolean = true
|
||||
open fun shouldSerializeTypeAlias(descriptor: TypeAliasDescriptor): Boolean = true
|
||||
open fun shouldSerializeNestedClass(descriptor: ClassDescriptor): Boolean = true
|
||||
|
||||
interface ClassMembersProducer {
|
||||
fun getCallableMembers(classDescriptor: ClassDescriptor): Collection<CallableMemberDescriptor>
|
||||
|
||||
@@ -11,3 +11,7 @@ class Outer {
|
||||
inner class Inner(x: Int = 1, y: String = "")
|
||||
class Nested(x: Int = 1, y: String = "")
|
||||
}
|
||||
|
||||
sealed class A(val x: String? = null) {
|
||||
class C : A()
|
||||
}
|
||||
|
||||
42
compiler/testData/asJava/ultraLightClasses/delegatesWithAnnotations.java
vendored
Normal file
42
compiler/testData/asJava/ultraLightClasses/delegatesWithAnnotations.java
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
@java.lang.annotation.Retention(null=java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
public abstract @interface SimpleAnn /* SimpleAnn*/ {
|
||||
@null()
|
||||
public abstract java.lang.String value();
|
||||
|
||||
}
|
||||
|
||||
@java.lang.annotation.Retention(null=java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
public abstract @interface Ann /* Ann*/ {
|
||||
@null()
|
||||
public abstract SimpleAnn[] t();
|
||||
|
||||
@null()
|
||||
public abstract java.lang.Class<?> z();
|
||||
|
||||
@null()
|
||||
public abstract java.lang.Class<?>[] e();
|
||||
|
||||
@null()
|
||||
public abstract java.lang.String y();
|
||||
|
||||
@null()
|
||||
public abstract kotlin.DeprecationLevel depr();
|
||||
|
||||
public abstract int x();
|
||||
|
||||
}
|
||||
|
||||
public abstract interface Base /* Base*/ {
|
||||
@Ann(null=1, null="134", null=String::class, null=arrayOf(Int::class, Double::class), null=DeprecationLevel.WARNING, null=SimpleAnn("243"), null=SimpleAnn("4324"))
|
||||
public abstract void foo(@Ann(null=2, null="324", null=Ann::class, null=arrayOf(Byte::class, Base::class), null=DeprecationLevel.WARNING, null=SimpleAnn("687"), null=SimpleAnn("78")) @org.jetbrains.annotations.NotNull() java.lang.String);
|
||||
|
||||
}
|
||||
|
||||
public final class Derived /* Derived*/ implements Base {
|
||||
@Ann(x=1, y="134", z=java.lang.String.class, e={int.class, double.class}, depr=kotlin.DeprecationLevel.WARNING, t={@SimpleAnn(value="243"), @SimpleAnn(value="4324")})
|
||||
public void foo(@Ann(x=2, y="324", z=Ann.class, e={byte.class, Base.class}, depr=kotlin.DeprecationLevel.WARNING, t={@SimpleAnn(value="687"), @SimpleAnn(value="78")}) @org.jetbrains.annotations.NotNull() java.lang.String);
|
||||
|
||||
@null()
|
||||
public Derived(@org.jetbrains.annotations.NotNull() Base);
|
||||
|
||||
}
|
||||
25
compiler/testData/asJava/ultraLightClasses/delegatesWithAnnotations.kt
vendored
Normal file
25
compiler/testData/asJava/ultraLightClasses/delegatesWithAnnotations.kt
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/** should load cls */
|
||||
annotation class SimpleAnn(val value: String)
|
||||
|
||||
/** should load cls */
|
||||
annotation class Ann(
|
||||
val x: Int,
|
||||
val y: String,
|
||||
val z: KClass<*>,
|
||||
val e: Array<KClass<*>>,
|
||||
val depr: DeprecationLevel
|
||||
vararg val t: SimpleAnn
|
||||
)
|
||||
|
||||
interface Base {
|
||||
@Ann(1, "134", String::class, arrayOf(Int::class, Double::class), DeprecationLevel.WARNING, SimpleAnn("243"), SimpleAnn("4324"))
|
||||
fun foo(
|
||||
@Ann(2, "324", Ann::class, arrayOf(Byte::class, Base::class), DeprecationLevel.WARNING, SimpleAnn("687"), SimpleAnn("78")) x: String
|
||||
)
|
||||
}
|
||||
|
||||
class Derived(b: Base) : Base by b {
|
||||
|
||||
}
|
||||
@@ -3,4 +3,8 @@ class MyException : Exception
|
||||
class C @Throws(Exception::class) constructor(a: Int = 1) {
|
||||
@Throws(java.io.IOException::class, MyException::class)
|
||||
fun readFile(name: String): String {}
|
||||
|
||||
// Should be mapped to java.lang.Throwable
|
||||
@Throws(kotlin.Throwable::class)
|
||||
fun baz() {}
|
||||
}
|
||||
|
||||
104
compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.instructions
vendored
Normal file
104
compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.instructions
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
== myRun ==
|
||||
inline fun Any?.myRun(block: () -> Unit): Unit {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
1 <START>
|
||||
v(block: () -> Unit)
|
||||
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
|
||||
w(block|<v0>)
|
||||
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() })
|
||||
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
|
||||
jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
|
||||
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[<SINK>]
|
||||
L2 [after local declaration]:
|
||||
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1> PREV:[jmp?(L2)]
|
||||
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
|
||||
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
|
||||
r(block) -> <v3>
|
||||
mark(block())
|
||||
call(block(), invoke|<v3>) -> <v4>
|
||||
ret(*|<v4>) L1
|
||||
L1:
|
||||
1 <END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
|
||||
=====================
|
||||
== anonymous_0 ==
|
||||
{
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
---------------------
|
||||
L3:
|
||||
3 <START>
|
||||
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
|
||||
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
|
||||
r(block) -> <v1>
|
||||
mark(InvocationKind.EXACTLY_ONCE)
|
||||
r(EXACTLY_ONCE) -> <v2>
|
||||
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
|
||||
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
|
||||
L4:
|
||||
3 <END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== test ==
|
||||
fun test(): String {
|
||||
val x: String? = null
|
||||
|
||||
x?.myRun {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
1 <START>
|
||||
2 mark({ val x: String? = null x?.myRun { return "" } })
|
||||
v(val x: String? = null)
|
||||
r(null) -> <v0>
|
||||
w(x|<v0>)
|
||||
mark(x?.myRun { return "" })
|
||||
jf(L2) NEXT:[<END>, r(x) -> <v1>]
|
||||
r(x) -> <v1>
|
||||
mark({ return "" })
|
||||
r({ return "" }) -> <v2>
|
||||
mark(myRun { return "" })
|
||||
call(myRun { return "" }, myRun|<v1>, <v2>) -> <v3>
|
||||
L3 [before inlined declaration]:
|
||||
inlined({ return "" }) NEXT:[<SINK>]
|
||||
L1:
|
||||
L2 [result of call]:
|
||||
L4 [after inlined declaration]:
|
||||
1 <END> NEXT:[<SINK>] PREV:[jf(L2), ret(*|<v0>) L1]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>, inlined({ return "" })]
|
||||
=====================
|
||||
== inlined anonymous_1 ==
|
||||
{
|
||||
return ""
|
||||
}
|
||||
---------------------
|
||||
L5:
|
||||
3 <START>
|
||||
4 mark(return "")
|
||||
mark("")
|
||||
r("") -> <v0>
|
||||
ret(*|<v0>) L1 NEXT:[<END>]
|
||||
L6:
|
||||
- 3 <END> NEXT:[<SINK>] PREV:[]
|
||||
error:
|
||||
- <ERROR> PREV:[]
|
||||
sink:
|
||||
- <SINK> PREV:[]
|
||||
=====================
|
||||
18
compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.kt
vendored
Normal file
18
compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.kt
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun Any?.myRun(block: () -> Unit): Unit {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun test(): String {
|
||||
val x: String? = null
|
||||
|
||||
x?.myRun {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
53
compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.values
vendored
Normal file
53
compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.values
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
== myRun ==
|
||||
inline fun Any?.myRun(block: () -> Unit): Unit {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
---------------------
|
||||
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
|
||||
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
|
||||
block <v3>: {<: () -> Unit} NEW: r(block) -> <v3>
|
||||
block() <v4>: Unit NEW: call(block(), invoke|<v3>) -> <v4>
|
||||
return block() !<v5>: *
|
||||
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
|
||||
=====================
|
||||
== anonymous_0 ==
|
||||
{
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
---------------------
|
||||
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
|
||||
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
|
||||
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
|
||||
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
|
||||
=====================
|
||||
== test ==
|
||||
fun test(): String {
|
||||
val x: String? = null
|
||||
|
||||
x?.myRun {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
null <v0>: {<: String?} NEW: r(null) -> <v0>
|
||||
x <v1>: * NEW: r(x) -> <v1>
|
||||
{ return "" } <v2>: {<: () -> Unit} NEW: r({ return "" }) -> <v2>
|
||||
myRun { return "" } <v3>: * NEW: call(myRun { return "" }, myRun|<v1>, <v2>) -> <v3>
|
||||
x?.myRun { return "" } <v3>: * COPY
|
||||
{ val x: String? = null x?.myRun { return "" } } <v3>: * COPY
|
||||
=====================
|
||||
== inlined anonymous_1 ==
|
||||
{
|
||||
return ""
|
||||
}
|
||||
---------------------
|
||||
"" <v0>: String NEW: r("") -> <v0>
|
||||
return "" !<v1>: *
|
||||
return "" !<v1>: * COPY
|
||||
=====================
|
||||
@@ -12,6 +12,6 @@ suspend fun test() = foo(A("O", "K")) { (x_param, y_param) -> x_param + y_param
|
||||
// VARIABLE : NAME=$x_param_y_param TYPE=LA; INDEX=5
|
||||
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=6
|
||||
// VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=7
|
||||
// VARIABLE : NAME=$i$a$2$foo TYPE=I INDEX=2
|
||||
// VARIABLE : NAME=$i$a$-foo-InlineKt$test$2 TYPE=I INDEX=2
|
||||
// VARIABLE : NAME=a$iv TYPE=LA; INDEX=1
|
||||
// VARIABLE : NAME=$i$f$foo TYPE=I INDEX=8
|
||||
|
||||
@@ -19,5 +19,5 @@ fun box(): String {
|
||||
// VARIABLE : NAME=a1 TYPE=Ljava/lang/String; INDEX=2
|
||||
// VARIABLE : NAME=a2 TYPE=Ljava/lang/String; INDEX=3
|
||||
// VARIABLE : NAME=a3 TYPE=I INDEX=4
|
||||
// VARIABLE : NAME=$i$a$1$foo TYPE=I INDEX=5
|
||||
// VARIABLE : NAME=$i$a$-foo-DestructuringInlineLambdaKt$box$1 TYPE=I INDEX=5
|
||||
// VARIABLE : NAME=$i$f$foo TYPE=I INDEX=6
|
||||
|
||||
@@ -14,7 +14,7 @@ class A {
|
||||
// METHOD : A.foo()V
|
||||
// VARIABLE : NAME=zzz TYPE=I INDEX=3
|
||||
// VARIABLE : NAME=it TYPE=I INDEX=2
|
||||
// VARIABLE : NAME=$i$a$1$inlineFun TYPE=I INDEX=4
|
||||
// VARIABLE : NAME=$i$a$-inlineFun-A$foo$1 TYPE=I INDEX=4
|
||||
// VARIABLE : NAME=this_$iv TYPE=LA; INDEX=1
|
||||
// VARIABLE : NAME=$i$f$inlineFun TYPE=I INDEX=5
|
||||
// VARIABLE : NAME=this TYPE=LA; INDEX=0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user