Support class literals (A::class)
This commit is contained in:
@@ -30,11 +30,11 @@ import kotlin.KotlinPackage;
|
|||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
|
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
|
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
|
||||||
import org.jetbrains.kotlin.codegen.inline.*;
|
import org.jetbrains.kotlin.codegen.inline.*;
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethod;
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethod;
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||||
@@ -2610,6 +2610,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return lookupLocalIndex(declarationDescriptor);
|
return lookupLocalIndex(declarationDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackValue visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, StackValue data) {
|
||||||
|
JetType type = bindingContext.get(EXPRESSION_TYPE, expression);
|
||||||
|
assert type != null;
|
||||||
|
|
||||||
|
assert state.getReflectionTypes().getkClass().getTypeConstructor().equals(type.getConstructor())
|
||||||
|
: "::class expression should be type checked to a KClass: " + type;
|
||||||
|
|
||||||
|
ClassifierDescriptor typeArgument = KotlinPackage.single(type.getArguments()).getType().getConstructor().getDeclarationDescriptor();
|
||||||
|
assert typeArgument instanceof ClassDescriptor : "KClass argument should be a class: " + typeArgument;
|
||||||
|
|
||||||
|
return generateClassLiteralReference((ClassDescriptor) typeArgument);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) {
|
public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) {
|
||||||
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression.getCallableReference(), bindingContext);
|
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression.getCallableReference(), bindingContext);
|
||||||
@@ -2690,10 +2704,22 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
@Override
|
@Override
|
||||||
public Unit invoke(InstructionAdapter v) {
|
public Unit invoke(InstructionAdapter v) {
|
||||||
v.visitLdcInsn(descriptor.getName().asString());
|
v.visitLdcInsn(descriptor.getName().asString());
|
||||||
|
StackValue receiverClass = generateClassLiteralReference(containingClass);
|
||||||
|
receiverClass.put(receiverClass.type, v);
|
||||||
|
v.invokestatic(REFLECTION, factoryMethod.getName(), factoryMethod.getDescriptor(), false);
|
||||||
|
|
||||||
Type classAsmType = typeMapper.mapClass(containingClass);
|
return Unit.INSTANCE$;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (containingClass instanceof JavaClassDescriptor) {
|
@NotNull
|
||||||
|
private StackValue generateClassLiteralReference(@NotNull final ClassDescriptor descriptor) {
|
||||||
|
return StackValue.operation(K_CLASS_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||||
|
@Override
|
||||||
|
public Unit invoke(InstructionAdapter v) {
|
||||||
|
Type classAsmType = typeMapper.mapClass(descriptor);
|
||||||
|
if (descriptor instanceof JavaClassDescriptor) {
|
||||||
v.aconst(classAsmType);
|
v.aconst(classAsmType);
|
||||||
v.invokestatic(REFLECTION, "foreignKotlinClass", Type.getMethodDescriptor(K_CLASS_TYPE, getType(Class.class)), false);
|
v.invokestatic(REFLECTION, "foreignKotlinClass", Type.getMethodDescriptor(K_CLASS_TYPE, getType(Class.class)), false);
|
||||||
}
|
}
|
||||||
@@ -2701,8 +2727,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
v.getstatic(classAsmType.getInternalName(), JvmAbi.KOTLIN_CLASS_FIELD_NAME, K_CLASS_TYPE.getDescriptor());
|
v.getstatic(classAsmType.getInternalName(), JvmAbi.KOTLIN_CLASS_FIELD_NAME, K_CLASS_TYPE.getDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
v.invokestatic(REFLECTION, factoryMethod.getName(), factoryMethod.getDescriptor(), false);
|
|
||||||
|
|
||||||
return Unit.INSTANCE$;
|
return Unit.INSTANCE$;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ public class GenerationState {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private List<ScriptDescriptor> earlierScriptsForReplInterpreter;
|
private List<ScriptDescriptor> earlierScriptsForReplInterpreter;
|
||||||
|
|
||||||
|
private final ReflectionTypes reflectionTypes;
|
||||||
|
|
||||||
private final JvmRuntimeTypes runtimeTypes;
|
private final JvmRuntimeTypes runtimeTypes;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -187,7 +189,7 @@ public class GenerationState {
|
|||||||
this.disableParamAssertions = disableParamAssertions;
|
this.disableParamAssertions = disableParamAssertions;
|
||||||
this.generateClassFilter = generateClassFilter;
|
this.generateClassFilter = generateClassFilter;
|
||||||
|
|
||||||
ReflectionTypes reflectionTypes = new ReflectionTypes(module);
|
this.reflectionTypes = new ReflectionTypes(module);
|
||||||
this.runtimeTypes = new JvmRuntimeTypes(reflectionTypes);
|
this.runtimeTypes = new JvmRuntimeTypes(reflectionTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,6 +261,11 @@ public class GenerationState {
|
|||||||
return generateClassFilter;
|
return generateClassFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public ReflectionTypes getReflectionTypes() {
|
||||||
|
return reflectionTypes;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JvmRuntimeTypes getJvmRuntimeTypes() {
|
public JvmRuntimeTypes getJvmRuntimeTypes() {
|
||||||
return runtimeTypes;
|
return runtimeTypes;
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ public interface JetNodeTypes {
|
|||||||
JetNodeType INDICES = new JetNodeType("INDICES", JetContainerNode.class);
|
JetNodeType INDICES = new JetNodeType("INDICES", JetContainerNode.class);
|
||||||
IElementType DOT_QUALIFIED_EXPRESSION = JetStubElementTypes.DOT_QUALIFIED_EXPRESSION;
|
IElementType DOT_QUALIFIED_EXPRESSION = JetStubElementTypes.DOT_QUALIFIED_EXPRESSION;
|
||||||
JetNodeType CALLABLE_REFERENCE_EXPRESSION = new JetNodeType("CALLABLE_REFERENCE_EXPRESSION", JetCallableReferenceExpression.class);
|
JetNodeType CALLABLE_REFERENCE_EXPRESSION = new JetNodeType("CALLABLE_REFERENCE_EXPRESSION", JetCallableReferenceExpression.class);
|
||||||
|
JetNodeType CLASS_LITERAL_EXPRESSION = new JetNodeType("CLASS_LITERAL_EXPRESSION", JetClassLiteralExpression.class);
|
||||||
JetNodeType SAFE_ACCESS_EXPRESSION = new JetNodeType("SAFE_ACCESS_EXPRESSION", JetSafeQualifiedExpression.class);
|
JetNodeType SAFE_ACCESS_EXPRESSION = new JetNodeType("SAFE_ACCESS_EXPRESSION", JetSafeQualifiedExpression.class);
|
||||||
|
|
||||||
JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.class);
|
JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.class);
|
||||||
|
|||||||
@@ -1466,7 +1466,7 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression) {
|
public void visitDoubleColonExpression(@NotNull JetDoubleColonExpression expression) {
|
||||||
mark(expression);
|
mark(expression);
|
||||||
createNonSyntheticValue(expression, MagicKind.CALLABLE_REFERENCE);
|
createNonSyntheticValue(expression, MagicKind.CALLABLE_REFERENCE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
* : (userType "?"*)? "::" SimpleName
|
* : (userType "?"*)? "::" SimpleName
|
||||||
* ;
|
* ;
|
||||||
*/
|
*/
|
||||||
private boolean parseCallableReferenceExpression() {
|
private boolean parseDoubleColonExpression() {
|
||||||
PsiBuilder.Marker expression = mark();
|
PsiBuilder.Marker expression = mark();
|
||||||
|
|
||||||
if (!at(COLONCOLON)) {
|
if (!at(COLONCOLON)) {
|
||||||
@@ -393,8 +393,14 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
advance(); // COLONCOLON
|
advance(); // COLONCOLON
|
||||||
|
|
||||||
parseSimpleNameExpression();
|
if (at(CLASS_KEYWORD)) {
|
||||||
expression.done(CALLABLE_REFERENCE_EXPRESSION);
|
advance(); // CLASS_KEYWORD
|
||||||
|
expression.done(CLASS_LITERAL_EXPRESSION);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parseSimpleNameExpression();
|
||||||
|
expression.done(CALLABLE_REFERENCE_EXPRESSION);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -416,8 +422,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
private void parsePostfixExpression() {
|
private void parsePostfixExpression() {
|
||||||
PsiBuilder.Marker expression = mark();
|
PsiBuilder.Marker expression = mark();
|
||||||
|
|
||||||
boolean callableReference = parseCallableReferenceExpression();
|
boolean doubleColonExpression = parseDoubleColonExpression();
|
||||||
if (!callableReference) {
|
if (!doubleColonExpression) {
|
||||||
parseAtomicExpression();
|
parseAtomicExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,7 +435,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
parseArrayAccess();
|
parseArrayAccess();
|
||||||
expression.done(ARRAY_ACCESS_EXPRESSION);
|
expression.done(ARRAY_ACCESS_EXPRESSION);
|
||||||
}
|
}
|
||||||
else if (!callableReference && parseCallSuffix()) {
|
else if (!doubleColonExpression && parseCallSuffix()) {
|
||||||
expression.done(CALL_EXPRESSION);
|
expression.done(CALL_EXPRESSION);
|
||||||
}
|
}
|
||||||
else if (at(DOT)) {
|
else if (at(DOT)) {
|
||||||
|
|||||||
@@ -19,26 +19,12 @@ package org.jetbrains.kotlin.psi;
|
|||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.kotlin.JetNodeTypes;
|
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
|
||||||
|
|
||||||
public class JetCallableReferenceExpression extends JetExpressionImpl {
|
public class JetCallableReferenceExpression extends JetDoubleColonExpression {
|
||||||
public JetCallableReferenceExpression(@NotNull ASTNode node) {
|
public JetCallableReferenceExpression(@NotNull ASTNode node) {
|
||||||
super(node);
|
super(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public JetTypeReference getTypeReference() {
|
|
||||||
return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public PsiElement getDoubleColonTokenReference() {
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
return findChildByType(JetTokens.COLONCOLON);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JetSimpleNameExpression getCallableReference() {
|
public JetSimpleNameExpression getCallableReference() {
|
||||||
PsiElement psi = getDoubleColonTokenReference();
|
PsiElement psi = getDoubleColonTokenReference();
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.psi
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
|
||||||
|
public class JetClassLiteralExpression(node: ASTNode) : JetDoubleColonExpression(node) {
|
||||||
|
override fun <R, D> accept(visitor: JetVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitClassLiteralExpression(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.psi
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.JetNodeTypes
|
||||||
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
|
|
||||||
|
public abstract class JetDoubleColonExpression(node: ASTNode) : JetExpressionImpl(node) {
|
||||||
|
public fun getTypeReference(): JetTypeReference? = findChildByType(JetNodeTypes.TYPE_REFERENCE)
|
||||||
|
|
||||||
|
public fun getDoubleColonTokenReference(): PsiElement = findChildByType(JetTokens.COLONCOLON)
|
||||||
|
|
||||||
|
override fun <R, D> accept(visitor: JetVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitDoubleColonExpression(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -258,10 +258,18 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
|
|||||||
return visitExpression(expression, data);
|
return visitExpression(expression, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public R visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, D data) {
|
public R visitDoubleColonExpression(@NotNull JetDoubleColonExpression expression, D data) {
|
||||||
return visitExpression(expression, data);
|
return visitExpression(expression, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public R visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, D data) {
|
||||||
|
return visitDoubleColonExpression(expression, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public R visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, D data) {
|
||||||
|
return visitDoubleColonExpression(expression, data);
|
||||||
|
}
|
||||||
|
|
||||||
public R visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, D data) {
|
public R visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, D data) {
|
||||||
return visitQualifiedExpression(expression, data);
|
return visitQualifiedExpression(expression, data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,10 +253,18 @@ public class JetVisitorVoid extends JetVisitor<Void, Void> {
|
|||||||
super.visitQualifiedExpression(expression, null);
|
super.visitQualifiedExpression(expression, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitDoubleColonExpression(@NotNull JetDoubleColonExpression expression) {
|
||||||
|
super.visitDoubleColonExpression(expression, null);
|
||||||
|
}
|
||||||
|
|
||||||
public void visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression) {
|
public void visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression) {
|
||||||
super.visitCallableReferenceExpression(expression, null);
|
super.visitCallableReferenceExpression(expression, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression) {
|
||||||
|
super.visitClassLiteralExpression(expression, null);
|
||||||
|
}
|
||||||
|
|
||||||
public void visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression) {
|
public void visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression) {
|
||||||
super.visitDotQualifiedExpression(expression, null);
|
super.visitDotQualifiedExpression(expression, null);
|
||||||
}
|
}
|
||||||
@@ -758,12 +766,24 @@ public class JetVisitorVoid extends JetVisitor<Void, Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Void visitDoubleColonExpression(@NotNull JetDoubleColonExpression expression, Void data) {
|
||||||
|
visitDoubleColonExpression(expression);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Void visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, Void data) {
|
public final Void visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, Void data) {
|
||||||
visitCallableReferenceExpression(expression);
|
visitCallableReferenceExpression(expression);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Void visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, Void data) {
|
||||||
|
visitClassLiteralExpression(expression);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Void visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, Void data) {
|
public final Void visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, Void data) {
|
||||||
visitDotQualifiedExpression(expression);
|
visitDotQualifiedExpression(expression);
|
||||||
|
|||||||
@@ -254,10 +254,18 @@ public class JetVisitorVoidWithParameter<P> extends JetVisitor<Void, P> {
|
|||||||
super.visitQualifiedExpression(expression, data);
|
super.visitQualifiedExpression(expression, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitDoubleColonExpressionVoid(@NotNull JetDoubleColonExpression expression, P data) {
|
||||||
|
super.visitDoubleColonExpression(expression, data);
|
||||||
|
}
|
||||||
|
|
||||||
public void visitCallableReferenceExpressionVoid(@NotNull JetCallableReferenceExpression expression, P data) {
|
public void visitCallableReferenceExpressionVoid(@NotNull JetCallableReferenceExpression expression, P data) {
|
||||||
super.visitCallableReferenceExpression(expression, data);
|
super.visitCallableReferenceExpression(expression, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitClassLiteralExpressionVoid(@NotNull JetClassLiteralExpression expression, P data) {
|
||||||
|
super.visitClassLiteralExpression(expression, data);
|
||||||
|
}
|
||||||
|
|
||||||
public void visitDotQualifiedExpressionVoid(@NotNull JetDotQualifiedExpression expression, P data) {
|
public void visitDotQualifiedExpressionVoid(@NotNull JetDotQualifiedExpression expression, P data) {
|
||||||
super.visitDotQualifiedExpression(expression, data);
|
super.visitDotQualifiedExpression(expression, data);
|
||||||
}
|
}
|
||||||
@@ -755,12 +763,24 @@ public class JetVisitorVoidWithParameter<P> extends JetVisitor<Void, P> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Void visitDoubleColonExpression(@NotNull JetDoubleColonExpression expression, P data) {
|
||||||
|
visitDoubleColonExpressionVoid(expression, data);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Void visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, P data) {
|
public final Void visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, P data) {
|
||||||
visitCallableReferenceExpressionVoid(expression, data);
|
visitCallableReferenceExpressionVoid(expression, data);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Void visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, P data) {
|
||||||
|
visitClassLiteralExpressionVoid(expression, data);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Void visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, P data) {
|
public final Void visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, P data) {
|
||||||
visitDotQualifiedExpressionVoid(expression, data);
|
visitDotQualifiedExpressionVoid(expression, data);
|
||||||
|
|||||||
+21
-6
@@ -453,13 +453,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetTypeInfo visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, ExpressionTypingContext context) {
|
public JetTypeInfo visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, ExpressionTypingContext context) {
|
||||||
JetTypeReference typeReference = expression.getTypeReference();
|
JetType receiverType = resolveDoubleColonExpressionType(expression, context);
|
||||||
|
// TODO: forbid type parameters & generic classes
|
||||||
|
ClassifierDescriptor classifier = receiverType.getConstructor().getDeclarationDescriptor();
|
||||||
|
return JetTypeInfo.create(
|
||||||
|
components.reflectionTypes.getKClassType(Annotations.EMPTY, (ClassDescriptor) classifier),
|
||||||
|
context.dataFlowInfo
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
JetType receiverType =
|
@Override
|
||||||
typeReference == null
|
public JetTypeInfo visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, ExpressionTypingContext context) {
|
||||||
? null
|
JetType receiverType = resolveDoubleColonExpressionType(expression, context);
|
||||||
: components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, false);
|
|
||||||
|
|
||||||
JetSimpleNameExpression callableReference = expression.getCallableReference();
|
JetSimpleNameExpression callableReference = expression.getCallableReference();
|
||||||
if (callableReference.getReferencedName().isEmpty()) {
|
if (callableReference.getReferencedName().isEmpty()) {
|
||||||
@@ -472,6 +478,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
|
return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private JetType resolveDoubleColonExpressionType(@NotNull JetDoubleColonExpression expression, ExpressionTypingContext context) {
|
||||||
|
JetTypeReference typeReference = expression.getTypeReference();
|
||||||
|
|
||||||
|
return typeReference == null
|
||||||
|
? null
|
||||||
|
: components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private JetType getCallableReferenceType(
|
private JetType getCallableReferenceType(
|
||||||
@NotNull JetCallableReferenceExpression expression,
|
@NotNull JetCallableReferenceExpression expression,
|
||||||
|
|||||||
@@ -16,15 +16,16 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.types.reflect
|
package org.jetbrains.kotlin.types.reflect
|
||||||
|
|
||||||
import kotlin.properties.Delegates
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
private val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect")
|
private val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect")
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ public class ReflectionTypes(private val module: ModuleDescriptor) {
|
|||||||
public fun getKExtensionFunction(n: Int): ClassDescriptor = find("KExtensionFunction$n")
|
public fun getKExtensionFunction(n: Int): ClassDescriptor = find("KExtensionFunction$n")
|
||||||
public fun getKMemberFunction(n: Int): ClassDescriptor = find("KMemberFunction$n")
|
public fun getKMemberFunction(n: Int): ClassDescriptor = find("KMemberFunction$n")
|
||||||
|
|
||||||
|
public val kClass: ClassDescriptor by ClassLookup
|
||||||
public val kTopLevelVariable: ClassDescriptor by ClassLookup
|
public val kTopLevelVariable: ClassDescriptor by ClassLookup
|
||||||
public val kMutableTopLevelVariable: ClassDescriptor by ClassLookup
|
public val kMutableTopLevelVariable: ClassDescriptor by ClassLookup
|
||||||
public val kMemberProperty: ClassDescriptor by ClassLookup
|
public val kMemberProperty: ClassDescriptor by ClassLookup
|
||||||
@@ -56,6 +58,11 @@ public class ReflectionTypes(private val module: ModuleDescriptor) {
|
|||||||
public val kTopLevelExtensionProperty: ClassDescriptor by ClassLookup
|
public val kTopLevelExtensionProperty: ClassDescriptor by ClassLookup
|
||||||
public val kMutableTopLevelExtensionProperty: ClassDescriptor by ClassLookup
|
public val kMutableTopLevelExtensionProperty: ClassDescriptor by ClassLookup
|
||||||
|
|
||||||
|
public fun getKClassType(annotations: Annotations, classDescriptor: ClassDescriptor): JetType {
|
||||||
|
val arguments = listOf(TypeProjectionImpl(Variance.INVARIANT, classDescriptor.getDefaultType()))
|
||||||
|
return JetTypeImpl(annotations, kClass.getTypeConstructor(), false, arguments, kClass.getMemberScope(arguments))
|
||||||
|
}
|
||||||
|
|
||||||
public fun getKFunctionType(
|
public fun getKFunctionType(
|
||||||
annotations: Annotations,
|
annotations: Annotations,
|
||||||
receiverType: JetType?,
|
receiverType: JetType?,
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class A
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val klass = A::class
|
||||||
|
return if (klass.toString() == "class A") "OK" else "Fail: $klass"
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
|
||||||
|
class A
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a1 = javaClass<A>().kotlin
|
||||||
|
val a2 = A::class
|
||||||
|
|
||||||
|
if (a1 != a2) return "Fail equals"
|
||||||
|
if (a1.hashCode() != a2.hashCode()) return "Fail hashCode"
|
||||||
|
if (a1.toString() != a2.toString()) return "Fail toString"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
class A
|
||||||
|
|
||||||
|
val k = A::class
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal val k: kotlin.reflect.KClass<A>
|
||||||
|
|
||||||
|
internal final class A {
|
||||||
|
public constructor A()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -28,6 +28,11 @@ fun ok() {
|
|||||||
a??::b
|
a??::b
|
||||||
a<b>?::c
|
a<b>?::c
|
||||||
a<b?,c?>?::d
|
a<b?,c?>?::d
|
||||||
|
|
||||||
|
A::class
|
||||||
|
a<b,c>::class
|
||||||
|
::class
|
||||||
|
a b ::class
|
||||||
}
|
}
|
||||||
|
|
||||||
fun err0() {
|
fun err0() {
|
||||||
|
|||||||
@@ -464,6 +464,51 @@ JetFile: DoubleColon.kt
|
|||||||
PsiElement(COLONCOLON)('::')
|
PsiElement(COLONCOLON)('::')
|
||||||
REFERENCE_EXPRESSION
|
REFERENCE_EXPRESSION
|
||||||
PsiElement(IDENTIFIER)('d')
|
PsiElement(IDENTIFIER)('d')
|
||||||
|
PsiWhiteSpace('\n\n ')
|
||||||
|
CLASS_LITERAL_EXPRESSION
|
||||||
|
TYPE_REFERENCE
|
||||||
|
USER_TYPE
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('A')
|
||||||
|
PsiElement(COLONCOLON)('::')
|
||||||
|
PsiElement(class)('class')
|
||||||
|
PsiWhiteSpace('\n ')
|
||||||
|
CLASS_LITERAL_EXPRESSION
|
||||||
|
TYPE_REFERENCE
|
||||||
|
USER_TYPE
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('a')
|
||||||
|
TYPE_ARGUMENT_LIST
|
||||||
|
PsiElement(LT)('<')
|
||||||
|
TYPE_PROJECTION
|
||||||
|
TYPE_REFERENCE
|
||||||
|
USER_TYPE
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('b')
|
||||||
|
PsiElement(COMMA)(',')
|
||||||
|
TYPE_PROJECTION
|
||||||
|
TYPE_REFERENCE
|
||||||
|
USER_TYPE
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('c')
|
||||||
|
PsiElement(GT)('>')
|
||||||
|
PsiElement(COLONCOLON)('::')
|
||||||
|
PsiElement(class)('class')
|
||||||
|
PsiWhiteSpace('\n ')
|
||||||
|
CLASS_LITERAL_EXPRESSION
|
||||||
|
PsiElement(COLONCOLON)('::')
|
||||||
|
PsiElement(class)('class')
|
||||||
|
PsiWhiteSpace('\n ')
|
||||||
|
BINARY_EXPRESSION
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('a')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
OPERATION_REFERENCE
|
||||||
|
PsiElement(IDENTIFIER)('b')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
CLASS_LITERAL_EXPRESSION
|
||||||
|
PsiElement(COLONCOLON)('::')
|
||||||
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
PsiElement(RBRACE)('}')
|
PsiElement(RBRACE)('}')
|
||||||
PsiWhiteSpace('\n\n')
|
PsiWhiteSpace('\n\n')
|
||||||
|
|||||||
+16
@@ -33,6 +33,7 @@ import java.util.regex.Pattern;
|
|||||||
@InnerTestClasses({
|
@InnerTestClasses({
|
||||||
JetDiagnosticsTestWithStdLibGenerated.Annotations.class,
|
JetDiagnosticsTestWithStdLibGenerated.Annotations.class,
|
||||||
JetDiagnosticsTestWithStdLibGenerated.CallableReference.class,
|
JetDiagnosticsTestWithStdLibGenerated.CallableReference.class,
|
||||||
|
JetDiagnosticsTestWithStdLibGenerated.ClassLiteral.class,
|
||||||
JetDiagnosticsTestWithStdLibGenerated.DuplicateJvmSignature.class,
|
JetDiagnosticsTestWithStdLibGenerated.DuplicateJvmSignature.class,
|
||||||
JetDiagnosticsTestWithStdLibGenerated.FunctionLiterals.class,
|
JetDiagnosticsTestWithStdLibGenerated.FunctionLiterals.class,
|
||||||
JetDiagnosticsTestWithStdLibGenerated.Inference.class,
|
JetDiagnosticsTestWithStdLibGenerated.Inference.class,
|
||||||
@@ -598,6 +599,21 @@ public class JetDiagnosticsTestWithStdLibGenerated extends AbstractJetDiagnostic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/classLiteral")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ClassLiteral extends AbstractJetDiagnosticsTestWithStdLib {
|
||||||
|
public void testAllFilesPresentInClassLiteral() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/classLiteral"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleClassLiteral.kt")
|
||||||
|
public void testSimpleClassLiteral() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/classLiteral/simpleClassLiteral.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/duplicateJvmSignature")
|
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/duplicateJvmSignature")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+22
@@ -2524,6 +2524,7 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection")
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@InnerTestClasses({
|
@InnerTestClasses({
|
||||||
|
Reflection.ClassLiterals.class,
|
||||||
Reflection.Enclosing.class,
|
Reflection.Enclosing.class,
|
||||||
Reflection.GenericSignature.class,
|
Reflection.GenericSignature.class,
|
||||||
Reflection.Mapping.class,
|
Reflection.Mapping.class,
|
||||||
@@ -2536,6 +2537,21 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ClassLiterals extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInClassLiterals() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleClassLiteral.kt")
|
||||||
|
public void testSimpleClassLiteral() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/simpleClassLiteral.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/enclosing")
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/enclosing")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
@@ -2712,6 +2728,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
doTestWithStdlib(fileName);
|
doTestWithStdlib(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("mappedClassIsEqualToClassLiteral.kt")
|
||||||
|
public void testMappedClassIsEqualToClassLiteral() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/mappedClassIsEqualToClassLiteral.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("memberProperty.kt")
|
@TestMetadata("memberProperty.kt")
|
||||||
public void testMemberProperty() throws Exception {
|
public void testMemberProperty() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/memberProperty.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/mapping/memberProperty.kt");
|
||||||
|
|||||||
+5
@@ -178,6 +178,11 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
return newVar(name, initializer).source(expression);
|
return newVar(name, initializer).source(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsNode visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, @NotNull TranslationContext context) {
|
||||||
|
throw new UnsupportedOperationException("Class literals are not yet supported: " + expression.getText());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsNode visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, @NotNull TranslationContext context) {
|
public JsNode visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, @NotNull TranslationContext context) {
|
||||||
|
|||||||
Reference in New Issue
Block a user